我有两个Python脚本,一个用子进程启动另一个
invoke.py:
import subprocess
p = subprocess.Popen(['python', 'long.py'])
print "Content-Type: text/plain\n"
print "invoked (%d)" % (p.pid)
longtime.py:
import time
import os
print "start (%d)" %(os.getpid())
time.sleep(10)
print "end (%d)" %(os.getpid())
当我从shell执行invoke.py时,它立即返回,longtime.py在后台运行(适用于Windows和Linux)。如果我通过Web界面(Apache CGI)调用invoke.py,它可以在Linux 下运行,但不能在Windows 机器上运行,那么网站就会卡住,只有在longtime.py完成后才会返回。
如何配置Python子流程或Apache以在Windows下获得相同的行为?差异是什么?
也许Windows上的Apache配置有些不同但我找不到东西。
Linux:Debian,Python2.5.2,Apache2.2.9
Windows:WinXP,Python2.7,Apache2.2.17
也许你也有一个更好的设计方法(因为我现在做的有点尴尬)。
为什么?:我在网络服务器上有一个脚本需要很长时间才能计算(longtime.py)。我想通过Web界面激活执行。网站应该立即返回,longtime.py应该在后台工作并将输出写入文件。稍后,来自Web界面的请求将检查文件是否已生成并读取输出。我不能使用常见的云提供者,因为他们不支持多线程。此外,我无法在Web服务器上安装守护程序处理程序,因为进程具有最大运行时间。
答案 0 :(得分:0)
我已经在Windows XP和OSX 10.6.6(shell)上测试了下面的代码,它在不等待子进程完成的情况下退出。
<强> invoke.py:强>
from subprocess import Popen, PIPE
import platform
if platform.system() == 'Windows':
close_fds=False
else:
close_fds=True
p = Popen('python long.py', stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=close_fds, shell=True)
print "Content-Type: text/plain\n"
print "invoked (%d)" % (p.pid)
<强> long.py 强>
import time
import os
print "start (%d)" %(os.getpid())
time.sleep(10)
print "end (%d)" %(os.getpid())
<强>更新强> 在Windows 7 + Apache 2.2.17 + Python 2.7 + mod_wsgi 3.3。
上测试mod_wsgi.so文件可以从here下载。 文件应重命名为mod_wsgi.so并放在apache模块文件夹中。
<强> invoke.wsgi:强> 来自子进程导入Popen,PIPE 导入平台
def application(environ, start_response):
if platform.system() == 'Windows':
close_fds=False
else:
close_fds=True
p = Popen('python "C:\testing\long.py"', stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=close_fds, shell=True)
status = '200 OK'
output = "invoked (%d)" % (p.pid)
response_headers = [('Content-type', 'text/plain'), ('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
long.py 文件保持不变。
对 httpd.conf :
的更改追加wsgi模块:
LoadModule wsgi_module modules/mod_wsgi.so
将目录添加到配置
<Directory "C:/testing">
AllowOverride None
Options None
Order allow,deny
Allow from all
</Directory>
将url链接到目录
Alias /testapp "C:\testing"
使用wsgi app链接网址
WSGIScriptAlias /testapp "C:\testing\invoke.wsgi"
重新启动网络服务器。 转http://server_name/testapp 应该显示进程ID并退出。