8. Python scripts
在Karrigell中运行Python脚本是非常简单的。打开我们喜欢的Python代码编辑器创建下面的脚本:
print "Hello Karrigell !"
然后把它保存在Root Directory下面的hello.py里。然后访问http://localhost/hello.py,我们就可以在浏览器里看到信息
Python脚本在Karrigell里是以普通的脚本方式运行的,它接受print语句发送数据到客户端浏览器而不是控制台窗口。
因此我们需要以适当的格式书写HTML代码;一个简单的表格我们可以这样写:
print "<TABLE>"
print "<TR>"
print "<TD>Name</TD>"
print "<TD>Address</TD>"
print "</TR>"
print "</TABLE>"
或者使用Python多行语法:
print """<TABLE>
<TR>
<TD>Name</TD>
<TD>Address</TD>
</TR>
</TABLE>"""
或者我们使用HTMLTags模块:
from HTMLTags import *
print TABLE(TR(TD("Name")+TD("Address")))
如果我们不想把脚本在karrigell里运行我们可以在脚本的最顶端包含这段代码:
try:
SCRIPT_END
except NameError:
pass
else:
print "This script can't be executed by Karrigell"
raise SCRIPT_END
(... rest of your script here ...)
如果SCRIPT_END在Python脚本的运行名字空间里那就是运行在Karrigell里,在这个情况下就会结束执行;如果从命令行执行就会触发NameError异常并且会忽略异常处理的脚本
9. CGI scripts
New in version 2.3.1
如果我们要在另一个环境上开发CGI脚本,我们可以不经过修改就能运行在Karrigell上。
提醒:在Karrigell 2.3.1里CGI脚本只能运行在异步服务器里,将会在以后添加其它服务器的支持
我们需要把CGI脚本放在一个特定的目录里。默认的是webapps/cgi-bin目录, 我们也可以设置配置文件里Directories下的cgi选项来指定其它的路径
10. Karrigell Services
10.1 Syntax
"Karrigell Services"也是一种Python脚本它可以处理一些URL,因此由不同的HTML页面组成的一个完整的服务可以创建在一个脚本文件里。
为了达到这样的目的,在Karrigell Service中的一个函数就映射着一个URL:在脚本dump.ks中的函数foo()可以调用dummy.ks/foo。
要调用方法foo(arg1,arg2),URL必须要像这样dummy.ks/foo?arg1=val1&arg2=val2或者通过一个带有字段arg1和arg2的表单来调用。
如果函数没有被指定,Karrigell会查找一个不带参数的index()函数。
为了安全和可读性的理由,函数只能清楚的定义在ks脚本里,并且它的定义在源代码中要以第一列开始才能够被调用。
如果我们需要在脚本里定义一个函数但又不想它通过一个url来被调用,可以在函数名字前加上一个下划线。
def _private(value):
"""Private function - can't be called from the outside"""
return value+1
为了从一个函数跳转到另外一个函数,可以为一个链接或一个表单的action属性指定一个函数名:
def index():
print '<a href="foo?name=bar">go to foo</a>'
def foo(name):
print '<IMG SRC="../picture.jpg">'
print name
注意foo()函数的第一行:因为这个URL决定的这个方法与文件或脚本相关连的URL同ks脚本是在同一个目录下,所以必须加上前缀"../"。
所有的HTTP环境变量,表单字段,自定义异常,身份认证函数,session控制等都在Python脚本中以相同的方式处于理。
下面是一个简单的Karrigell Service例子:
so = Session()
if not hasattr(so, 'x'):
so.x = 0
def index():
print "x = %s" %so.x
print '<br><a href="increment">Increment</a>'
print '<br><a href="decrement">Decrement</a>'
print '<br><a href="reset">Reset</a>'
def increment():
so.x = _private(so.x)
raise HTTP_REDIRECTION,"index"
def decrement():
so.x -= 1
raise HTTP_REDIRECTION,"index"
def reset():
so.x = 0
raise HTTP_REDIRECTION,"index"
def _private(x):
"""The function name begins with _ : internal function,
can't be call by a url"""
return x+1
10.2 Smart urls
在访问Karrigell Services时url上带有附加的参数有的时候是非常有用的。例如,地址htpp://path/service.ks/function/foo/bar?name=smith
将会使用'foo'和'bar'作为参数来调用function.
它们可以在脚本中调用THIS的subpath属性。在下面的例子中将会列出['foo','bar']
def function(name):
print 'subpath ',THIS.subpath
print name
"smart urls"的一个问题是当我们要写一个链接或使用Include()或重定向到一个相关的url,我们就需要给出一个正确的url,
是的,要预先考虑好在目标url前有几个'../'。
有几个'../'可以由subpath属性的长度来决定,如果我们想在下面的一个函数里写一个链接就需要这样写:
def function(name):
print 'subpath ',THIS.subpath
print name
print '<a href=%slogin>Login</a>' %('../'*len(THIS.subpath))
或者使用THIS的up属性:def function(name):
print 'subpath ',THIS.subpath
print name
print '<a href=%slogin>Login</a>' %THIS.up11. Python Inside HTML
Python Inside HTML很像微软的ASP及Sun的JSP和PHP;它们基本上是HTML文档,使用编程语言在其中插入部分代码,当然了在这里指的是Python。
在Python Inside HTML中,HTML代码使用特殊的标签<%和%>来分开Python代码。
假设我们想显示当前日期,我们将像这样混合Python和HTML代码:
The current date is
<% import time
print time.strftime("%d:%m:%y",time.localtime(time.time()))
%>使用文本编辑器,输入上面的代码并且把它保存到Root Directory下的time.pih里。在浏览中输入http://localhost/time.pih然后看发生了什么。
我们会注意到在<%和%>中的代码是普通的Python代码,在其中我们可以导入模块,创建和实例化类,使用变量,读写文件系统等。可以像在Python脚本中一样访问HTTP变量,表单字段,及Karrigell定义的异常。
11.1 Python variables
当我们只需要打印变量的值时,可以使用<%=var%>来代替<%print var%>:
Current directory <%= os.getcwd() %>
在这个例子中我们会注意到我们不需要显示地导入os模块:为了方便,在我们执行这个脚本的时候它已经在当前名字空间里了。还有string和Cookie模块也被导入了,因为它们可能会被大多数的脚本使用(当然,如果我们显式的使用import string我们的脚本也会正常的工作).。
11.2 Strings for translation
一直以来在Karrigell中国际化都是非常重要的部分,当我们想根据用户的参数选择来翻译字符串时可以使用<%_string%>
<% import time %>
<%_ "Current directory is " %> <%= os.getcwd() %>
<%_ "Current day " %> <%_ time.strftime("%a",time.localtime()) %>如果我们已经为字符串Current directory is准备好了译文,当用户调用这个脚本时并且它的语言选择的是法语,那么他的浏览器将会显示Le répertoire courant est。
参见Karrigell support for internationalization
11.3 Indentation
因为PIH文件里有Python代码的导致这些代码必须缩进。因为PIH脚本混合了HTML,为了更好的可读性并且把Python代码分块所以要使用缩进,使用恰当的缩进可以使提取代码与可读性变得不是很困难。
11.3.1 Basics
Python Inside HTML遵循以下简单的规则:
- 在脚本的开始处缩进为0
- 每一部分的缩进都要根据当前缩排
- 当前缩排可以两种意思:
- 当Python代码以冒号结束时,下一行的缩进将自增1
- 为了结束缩排要使用<%end%>
一个简单的条件例子:
# indentation | |
<% if hour<12: %> Good morning <% end> <% elif hour<18: %> Good afternoon <% end> <% else: %> Good evening <% end> Ladies and Gentlemen | # 0 - next one : 1 # 1 # 1 - next one : 0 # 0 - next one : 1 # 1 # 1 - next one : 0 # 0 - next one : 1 # 1 # 1 - next one : 0 # 0 |
一个for循环的例子:
# indentation | |
<table border=1> <tr> <th>Number</th> <th>Square</th> </tr> <% for i in range(10): %> <tr> <td><% print i %></td> <td><% print i**2 %></td> </tr> <% end %> </table> | # 0 # 0 # 0 # 0 # 0 # 0 - next one : 1 # 1 # 1 # 1 # 1 # 1 - next one 0 # 0 |
如果没有<%end%>标签,</table>标签将会被插入到当前循环中
最后一个是有两个级别缩排的例子:
# indentation | |
<% for i in range(10): %> <% if i % 2: %> <td class="odd"><%= i %></td> <% end %> <% else: %> <td class="even"><%= i %></td> <% end %> <% end %> End of table | # 0 - next one : 1 # 1 - next one : 2 # 2 # 2 - next one : 1 # 1 - next one : 2 # 2 # 2 - next one : 1 # 1 - next one : 0 # 0 |
注意在第一行必须使用%>关闭标签,否则在第二行时缩排仍是1。
11.3.3 The <indent> tag
在比较长的或更复杂的代码中重复使用<%end%>将会使代码变得冗长。如果想让PIH中的一些代码像在Python中一样缩进的话,可以嵌入<indent>标签。
第一个例子:
# indentation | |
<indent> <% if hour<12: %> Good morning <% elif hour<18: %> Good afternoon <% else: %> Good evening Ladies and Gentlemen </indent> | # 0 # 0 # 1 # 0 # 1 # 0 # 1 # 0 |
第二个例子:
# indentation | |
<table border=1> <tr> <th>Number</th> <th>Square</th> </tr> <indent> <% for i in range(10): %> <tr> <td><% print i %></td> <td><% print i**2 %></td> </tr> </indent> </table> | # 0 # 0 # 0 # 0 # 0 # 0 # 0 (A) # 1 # 1 # 1 # 1 # next one : 0 # 0 |
在注意事项(A)那一行上面我们看到了使用了<indent>标签来表示开始缩排
我们也注意到了在缩进部分结束的时候缩排返回了0
这是一个嵌套循环的例子:
<indent>
<table border=1>
<% for i in
['h']+range(10): %>
<tr>
<% for j in ['h']+range(10):
%>
<% if i!='h' and j!='h': %>
<td><%= i*j %></td>
<% elif i!='h':
%>
<th><%= i %></th>
<% elif
j!='h': %>
<th><%= j %></th>
<% else: %>
<td>*</td>
</tr>
</table>
</indent>
11.4 PIH as a templating system
PIH脚本可以在Karrigell server外用于创建HTML文件,把它当作"模板系统"。
例如,下面的这个HTML文档是一个PIH脚本。chapter号码不是固定的但是可以像这样插入到HTML中:
<h1><%= chapter %>. Python Inside HTML</h1>
为了从一个PIH脚本中处理HTML,可以使用Template模块,可以使用getScript(fileName)函数创建一个脚本的实例,然后应用它的render(nameSpace)方法,传递当前名字空间(通常是globals()或locals())它将会发现需要的变量。render方法返回一个Output实例,它的value属性就是返回的HTML结果:
import
Template
pihIn=Template.getScript("pythoninsidehtml.pih")
chapter=5
htmlOutput=pihIn.render(globals()).value
11.5 Debugging
为了调试可以启动PIHapp.py脚本。这是一个小型的GUI应用程序它展示PIH文件如何转换成Python脚本。结果可以被保存成一个HTML文件并且显示在浏览器上,如果没有使用变量调用它的语法是高亮显示的。