最近一周在用fabric结合web.py,用全python的环境,开发一套web版的自动发布系统,目前基本功能都已正常,后续还有很多的优化功能,主要有:
1、页面友好显示发布进度;
花费4天做出来的简陋系统,目前只支持某个功能完毕后,统一将结果反馈给用户,不支持交互,在0.3版本中,这个进度显示将会被解决,但是只限与chrome/ff这两个浏览器,因为经过我测试,ie7在接收到'Transfer-Encoding','chunked'这个http头之后,还是会缓存所有内容,最后一次显示给用户,而chrome/ff则不会,即使只有一个字符,他们还是按规矩显示在页面上,这个功能的确是我所需要的,这样用户就能时时看到发布进度了。
说到浏览器的缓存,不的不提的是nginx这个服务器的缓存,我勒个去啊,浪费了我最少2天的时间,就是因为nginx通过fastcgi连接web.py的时候,老是缓存,搞的我不知道到底哪个环节数据被缓存了,是在浏览器端?nginx端?fastcgi端?python的return端?一点头绪都没有,翻遍了google,最后狠心重新编译了python,将架构换成了apache2.2的最新版+wsgi+web.py,问题最终得到了解决,看来nginx也不是适合所有的场景,不过这个缓存的问题,在0.4版中会全面解决,用我下面提到的comet的技术。
2、页面交互。
这个功能也是非常实用的功能,比如发布到某台机器,应用也重启了,可是前台返回很多的报错,这时候我就需要中断发布了,研究了很久,最终确定下来用comet架构来做服务器推的交互。
好了,说说今天解决的两个技术细节,一个是下午百忙之中解决的,一个是回来晚上解决的:
1、python 读管道直到结束
这是可以正常工作的程序:
#from subprocess import *
import subprocess
#p = subprocess.Popen(["cat", "-n",'test.txt',';','sleep','3',';',"cat", "-n",'test.txt'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = False)
p = subprocess.Popen(["/bin/sh", "test.sh"], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = False)
while True:
pstr = p.stdout.readline()
if pstr:
print pstr
else:
break
这是之前不明白的时候写的:
#from subprocess import *
import subprocess
#p = subprocess.Popen(["cat", "-n",'test.txt',';','sleep','3',';',"cat", "-n",'test.txt'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = False)
p = subprocess.Popen(["/bin/sh", "test.sh"], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = False)
while True:
print p.stdout.readline()
现在明白管道的道理了,说来的确是在实践中才明白的:理解它的最关键点在于:脚本中sleep的时候,读管道的操作其实是被阻塞了,而并不是之前理解的那样“读到的是空串”,这个道理明白了,读管道的问题也就顺利解决了。
2、在函数中返回给GET方法,让他回显给浏览器
这个技术实现真的好蛋疼啊,因为根据之前的c/shell等编程经验,我都知道,在一个函数调用时,是不可能返回两次以上的东西给调用端的,但是今天下午忙完了一个urs的大维护后,不经意地竟然解决了这个大难题,真是爽,下面看代码:
def my_func():
for i in range(1,6):
func_str = str(i) + "
"
logging.info(func_str)
yield func_str
time.sleep(1)
class haha:
def GET(self):
web.header('Content-Type', 'text/html; charset=UTF-8')
web.header("Cache-Control", "no-cache, must-revalidate")
web.header("Expires", "Mon, 26 Jul 1997 05:00:00 GMT")
logging.info("end, n:\n")
c = my_func()
try:
while True:
n = c.next()
yield n
except StopIteration:
pass
yield "output end"
根本的原理在于对yield 的理解,而对yield 的理解,根本的也在与,调用了next方法后,返回的是yield 表达式右边的串。
今天就到这里了,后续的事情就比较清晰了,本来以为要研究一个月的难题,两天就解决了,而这一切竟然发生在对python根本不熟悉的基础上! 多亏了之前c和shell的编程经验啊。
阅读(1671) | 评论(0) | 转发(0) |