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

在Windows中,就是这样。

我认为这个问题的答案是我需要创build一个Windows服务。 这似乎是我尝试做的很可笑的重量级。

我只是想在这里为我的经理打一个小原型,我不会负责生产这个原型……事实上,它甚至可能不会被生产; 这可能只是一些研究人员玩弄的东西。

我有一个CGI脚本,接收一个file upload,将其存储到一个临时的位置,然后启动一个后台进程来做一些严重的数字运算文件。 然后一些Javascript的东西坐在调用其他CGI脚本来检查状态,并根据需要更新页面。

所有这些工作,除了该死的Web服务器将不会closures连接,只要该subprocess正在运行。 我已经做了一些search,看来在Unix上的答案是使它成为一个守护进程,但我现在被困在Windows上,我想答案就是使它成为一个Windows服务?! 这似乎令人难以置信的重量级,只是,你知道,启动一个该死的进程,然后closures服务器连接。

这真的是唯一的方法?

编辑:好的,在这里find一个漂亮的小黑客(这个家伙给出的select(3)): 如何在IIS下的Perl CGI中完成后台进程

我可以修改它,使其更简单,虽然这是一个klugey解决scheme,它是我想做的快速和肮脏的小原型的完美。

所以我最初有我的主要脚本这样做:

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

正如我所描述的,这不起作用。 相反,我现在已经有了我的主脚本发出这个Javascript文件完全加载后运行的一点点的东西:

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

然后launchBackgroundProcess.py执行subprocess.Popen。

该解决scheme永远不会缩放,因为在后台任务运行的整个过程中仍然保持打开浏览器连接。 但是,由于这个小小的臃肿,我可能有一天会有两个同时在线的用户(即使那时我怀疑)资源也不是问题。 这允许用户查看主页面,并获得Javascript更新,即使仍然有一个http连接没有正确的理由。

感谢您的答案! 如果我被要求产品化,我会采取Profanebuild议的资源。

如果你没有太多的Windows编程经验,也不想仔细阅读MSDN文档 – 我不怪你 – 你可能想尝试拿起一个马克·哈蒙德的所有东西的python和指导的副本,视窗。 它不知何故在许多这样的反复出现的问题上过时。 而不是每个平台的解决方案启动的过程中,你可能会更好使用win32process模块​​。 哈蒙德书的第17章涵盖了这个广泛的,但你可能可以通过下载pywin ide(我认为它捆绑在你可以从pypi下载的windows扩展中)来获得所有你需要的东西,然后查看它的帮助文档蟒蛇的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) 

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

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

您可以使用“开始”Windows命令使用system调用。 这样你的python脚本就不会等待启动程序的完成。

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

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

如果子进程在Perl中,我想你可以很简单地关闭句柄:

 close(STDOUT); 

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