在Karrigell中有好几种写程序的方式:
这些不同的编程方式都使用相同的方式访问HTTP环境变量和表单数据,这些都会在下面的文档里分别描述。
我们也可以使用其它几种受支持的脚本:如果想使用.foo来管理脚本,我们可以写一个叫作mod_foo的模块。可以参见使用mod_tmpl.py管理Cheetah模板系统管理的例子。
在Karrigell脚本运行的名字空间里提供通过全局变量来访问HTTP环境变量:
QUERY是一个字典变量代表着当使用HTTP GET方法或HTTP POST方法提交表单数据时的查询字符串。QUERY的键名字就是表单中的字段名,它的值就是字符串形式的字段值,或当字段名以[ ]结尾时使用列表来表示字段的值(比如一个<SELECT MULTIPLE>表单字段)
假设我们有这样一个HTML表单:
<form action="myScript.py">
Spam <input name="spam">
<br><select multiple name="animal[]">
<option value="dog">Dog
<option value="cat">Cat
<option value="frog">Frog
</select>
<br><input type="submit" value="Ok">
</form>
在myScript.py中input字段将会这样被显示:
print "<br>Spam is ",QUERY["spam"]
if QUERY.has_key("animal"):
print "<br>Animal is ",str(QUERY["animal"])
可以通过一种快捷方式来访问这些数据,即使用_与字段名组合起来。下面的代码将会像这样写:
print "<br>Spam is ",_spam
if QUERY.has_key("animal"):
print "<br>Animal is ",str(_animal)
使用下划线是为了避免字段名与Python保留字或相同的模块名字冲突
通常情况下往一个脚本里传递参数是在url里使用查询字符串或者post数据,而另一种选择是把参数作为url的一部分来传递,就像http://host/path/script.py/foo/bar ,这里的参数就是foo和bar
在脚本里我们可以通过一个列表来访问这些参数,它是THIS的一个属性即THIS.subpath:
print "The parameters are %s" %THIS.subpath
这个url存在的问题是当我们使用Include或写一个相关的链接或插入一个图像或JavaScript,如果调用这个脚本没有使用subpath或subpath中有一些参数这时url肯定会有所不同.
例如在脚本里写这样一个相关的url:
print '<IMG SRC="images/pic.png">'
然后调用这个脚本http://host/path/script.py/foo/bar,浏览器将会计算绝对路径,点击这个链接后:
http://host/path/script.py/foo/images/pic.png,使用参数foo,images,pic.png执行相同的脚本显然这不是我们想要的。
因此如果我们计划在一个子路径里传递一个参数,将必须像这样写相关的url:
print '<IMG SRC="%simages/pic.png">' %THIS.up
THIS.up代表着有多少参数就会有多少个字符串'../'
我们也可以使用baseurl属性,它将会返回当前的路径path/
为了从客户端上传一个文件到服务器端,表单中的input标签必须有一个类型为'file'的。比如有一个表单像这样:
<FORM ENCTYPE="multipart/form-data" ACTION="fileUpload.py" METHOD=POST>
File to process: <INPUT NAME="myfile" TYPE="file">
<INPUT TYPE="submit" VALUE="Send File">
</FORM>
那个脚本使用变量QUERY['myfile']或_myfile来处理要上传的文件,它是cgi模块内置类FieldStorage的一个实例。
这个对象有两个属性:
filename:文件的名字
file:一个像file的对象可用来读取文件的内容
例如我们想在服务器端的文件系统使用相同的文件名保存文件:
import os
f = _myfile.file # file-like object
dest_name = os.path.basename(_myfile.filename)
out = open(dest_name,'wb')
# copy file
import shutil
shutil.copyfileobj(f,out)
out.close()
在Karrigell的Python脚本中可以触发特殊的异常来处理脚本
SCRIPT_END
当我们想停止发送数据到浏览器又不想让脚本执行到文件末尾可以使用这个异常。这个异常在我们调试脚本或想让它某个
地方停止运行以查看脚本状态或变量值时非常有用
myVar=10
...
print myVar
raise SCRIPT_END
... (rest of code - won't be run)
SCRIPT_ERROR
使用raise SCRIPT_ERROR,msg来停止脚本的执行并输出msg
HTTP_ERROR
raise HTTP_ERROR,(errorCode,errorMessage)将导致Karrigell使用一个特定的错误代码和信息发送一个HTTP错误信息
HTTP_REDIRECTION
raise HTTP_REDIRECTION,url将导致Karrigell重定向一个请求到一个给定的URL
HTMLStream是HIP模块里面的一个类它比重复使用print语句要容易。它的设计像HTML Inside Python但使用不同的实现方式
创建这个类的一个实例:
import HIP
H = HIP.HTMLStream()
然后使用"+"和"-"来打印数据到标准输出:使用"+"数据将当作字符串被打印出来,使用"-"将使用cgi-escaped格式输出
aDict={"one":"unan","two":"daou","three":"tri"}
H + aDict - type(aDict)
它们和下面的代码是一样的:aDict={"one":"unan";"two":"daou";"three":"tri"}
print str(aDict),cgi.escape(type(aDict))7. Debugging
7.1 Debug mode
当我们测试新版本程序时,我们要重新导入改变后的模块通常会有些情形。考虑到性能的原因,标准Python解释器会导入模块已编译过的版本,而不会检查它的源代码是否修改过
我们可以设置配置文件里的reloadModules选项为1,它会强制加载这个模块最后一次修改的版本
一旦这个程序正式工作后,我们可以设置它的调试模式为0
7.2 Error handling and debugging
当我们调用一个URL发生错误时,将会在浏览器里显示一个调用栈
这些信息包括以下几个部分:
例如:
Error in /demo/errors/ErrorInIncludedTest1.py
/demo/errors/ErrorInIncludedTest1.py
includes /demo/errors/ErrorInIncludedTest2.py
Script /demo/errors/ErrorInIncludedTest1.py NameError: name 'bonjour' is not defined |
Traceback (most recent call last):
File "C:/cygwin/home/Karrigell/Template.py", line 153, in render
exec self.pythonCode() in ns
File "<string>", line 1, in ?
NameError: name 'bonjour' is not defined
点击这个"Debug"按钮我们还可以得到关于这个错误的更多信息:
屏幕截图:
如果我们不想让用户看到这些信息,我们可以设置配置文件里的debug选项为0