Chinaunix首页 | 论坛 | 博客
  • 博客访问: 69547
  • 博文数量: 24
  • 博客积分: 81
  • 博客等级: 民兵
  • 技术积分: 136
  • 用 户 组: 普通用户
  • 注册时间: 2011-12-08 00:56
文章分类
文章存档

2012年(9)

2011年(15)

我的朋友

分类:

2011-12-10 00:34:29

原文地址:python 读管道直到结束 作者:net_liufeng

    最近一周在用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) |
给主人留下些什么吧!~~