有没有一种简单的方法可以从Python CGI脚本启动后台任务而无需等待它终止?

时间:2011-09-21 16:48:20

标签: python windows cgi

在Windows中,即。

我认为这个问题的答案是我需要创建一个Windows服务。对于我想要做的事情,这似乎是非常重要的。

我只是想为我的经理在这里拍一个小原型,我不会负责产品化......事实上,它甚至可能永远不会被产品化;它可能只是少数研究人员在玩的东西。

我有一个CGI脚本,它接收一个文件进行上传,将其存储到临时位置,然后启动后台进程对文件进行一些严重的数字处理。然后,一些Javascript东西围绕调用其他CGI脚本来检查状态并根据需要更新页面。

所有这一切都有效,只要该子进程正在运行,该死的Web服务器将不会关闭连接。我已经做了一些搜索,看来Unix上的答案就是让它成为一个守护进程,但我现在仍然停留在Windows上,我想答案就是让它成为一个Windows服务?!?这看起来非常重要,你知道,启动一个该死的过程,然后关闭服务器连接。

那真的是唯一的方法吗?

编辑:好的,在这里发现了一个漂亮的小黑客(该家伙给出的选择(3)): How to completely background a process in Perl CGI under IIS

我能够对其进行修改以使其更简单,虽然这是一个非常简单的解决方案,但它非常适合我想要的快速而肮脏的小型原型。

所以我最初让我的主脚本执行此操作:

subprocess.Popen("python.exe","myscript.py","arg1","arg2")

正如我所描述的那样,哪个不起作用。相反,我现在让我的主脚本发出一点Javascript,它在文档完全加载后运行:

$("#somecrap").load("launchBackgroundProcess.py", {arg1:"foo",arg2:"bar"});

然后launchBackgroundProcess.py执行subprocess.Popen。

此解决方案永远不会扩展,因为在后台任务运行的整个过程中,它仍然会打开浏览器连接。但是,由于这个更小的我正在鞭打可能有一天最多有两个同时用户(即使我怀疑它)资源也不是问题。这允许用户查看主页面并获取Javascript更新,即使仍有一个http连接挂起,没有充分的理由。

感谢您的回答!如果我被要求进行产品化,我将采用Profane推荐的资源。

4 个答案:

答案 0 :(得分:1)

最简单但不是最有效的方法是运行另一个python可执行文件

from subprocess import Popen 
Popen("python somescript.py")

答案 1 :(得分:1)

您可以使用“start”windows命令使用system来电。这样你的python脚本就不会等待已启动程序的完成。

答案 2 :(得分:1)

如果您对Windows编程没有太多经验并且不想仔细阅读MSDN文档 - 我不会责怪您 - 您可能想要尝试获取Mark Hammond的所有指南的副本事python和windows。它在某种程度上永远不会过时出现在许多这类反复出现的问题上。而不是使用每个平台的解决方案启动流程,您可能最好使用win32process模块​​。 Hammond书的第17章详细介绍了这一点,但你可以通过下载pywin ide(我认为它捆绑在你可以从pypi下载的windows扩展中)来获得所需的一切,并查看它所拥有的帮助文档。 python的windows'api。这是一个使用api的例子,来自我最近工作的一个项目。事实上它可能会做一些你想要的东西,稍微调整一下。您可能希望专注于CreationFlags。特别是,win32process.DETACHED_PROCESS“经常用于在后台执行控制台程序”。许多其他标志可用,但方便包装。

    if subprocess.mswindows:
        su=subprocess.STARTUPINFO()
        su.dwFlags |= subprocess._subprocess.STARTF_USESHOWWINDOW
    process = subprocess.Popen(['program', 'flag', 'flag2'], bufsize=-1,
              stdout=subprocess.PIPE, startupinfo=su)

答案 3 :(得分:0)

CGI脚本在标准输出重定向的情况下运行,可以直接连接到TCP套接字或管道。通常,在句柄及其所有副本都关闭之前,连接不会关闭。默认情况下,子进程将继承句柄的副本。

有两种方法可以阻止连接等待子进程。一种是防止子进程继承句柄,另一种是让子进程在启动时关闭其句柄副本。

如果子进程在Perl中,我认为你可以非常简单地关闭句柄:

close(STDOUT);

如果要阻止子进程继承句柄,可以使用SetHandleInformation函数(如果可以访问Win32 API)或在调用CreateProcess时将bInheritHandles设置为FALSE。或者,在启动子进程之前关闭句柄。