如何在Windows下通过Apache立即生成Python2.5进程

1 投票
1 回答
692 浏览
提问于 2025-04-16 13:34

我有两个Python脚本,一个是用来启动另一个的,使用了subprocess模块。

第一个脚本是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())

当我在命令行中执行invoke.py时,它会立即返回,而longtime.py会在后台运行(在Windows和Linux上都可以)。但是如果我通过网页接口(Apache CGI)来调用invoke.py,在Linux上是可以的,但在Windows机器上就不行了,网站会卡住,直到longtime.py执行完才会返回。

我该如何配置Python的subprocess或Apache,以便在Windows上也能实现相同的效果?这两者有什么不同呢?

可能Windows上的Apache配置有些不同,但我没有找到相关的信息。

Linux环境:Debian,Python2.5.2,Apache2.2.9
Windows环境:WinXP,Python2.7,Apache2.2.17

也许你有更好的设计思路(因为我现在的做法有点尴尬)。

为什么要这样做呢?我在网页服务器上有一个脚本需要很长时间来计算(longtime.py)。我想通过网页接口来启动这个脚本。网站应该立即返回,而longtime.py应该在后台运行并将输出写入文件。之后,网页接口会检查这个文件是否生成,并读取输出。我不能使用常见的云服务提供商,因为它们不支持多线程。同时,我也不能在网页服务器上安装守护进程,因为进程有最大运行时间限制。

1 个回答

0

我在Windows XP和OSX 10.6.6上测试了下面的代码,发现它在没有等待子进程完成的情况下就退出了。

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文件。 这个文件需要重命名为mod_wsgi.so,并放在Apache的模块文件夹里。

invoke.wsgi: 从subprocess导入Popen和PIPE 导入platform

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>

将网址链接到目录

Alias /testapp "C:\testing"

将网址链接到wsgi应用

WSGIScriptAlias /testapp "C:\testing\invoke.wsgi"

重启网络服务器。 然后访问 http://server_name/testapp 应用应该会显示进程ID并退出。

撰写回答