在Django中提供Web请求时,我需要启动pdftk进程,并等待其完成。我当前的pdftk代码如下所示:

proc = subprocess.Popen(["/usr/bin/pdftk",
                         "/tmp/infile1.pdf",
                         "/tmp/infile2.pdf",
                         "cat", "output", "/tmp/outfile.pdf"])
proc.communicate()

只要我在开发服务器下执行(以www-data用户身份运行),就可以正常工作。但是,当我切换到mod_wsgi时,只要不进行任何其他更改,代码就会卡在proc.communicate()上,并且将“outfile.pdf”保留为零长度的打开文件句柄。

我已经尝试了子流程调用的几种变体(以及普通的旧os.system)-将stdin/stdout/stderr设置为PIPE或各种文件句柄都不会改变。使用“shell = True”可以防止proc.communicate()挂起,但是pdftk无法在devserver或mod_wsgi下创建输出文件。 This discussion似乎表明操作系统信号和pdftk可能还有一些更深的伏都教,我不了解。

是否有任何变通办法来获得这样的子流程调用,以便在wsgi下正常工作?我避免使用PyPDF合并pdf文件,因为我必须合并足够多的文件(数百个),以致其内存不足(PyPDF在合并它们时需要使每个源pdf文件在内存中保持打开状态)。

我正在最近的Ubuntu pythons 2.6和2.7下执行此操作。

最佳答案

尝试使用绝对文件系统路径输入和输出文件。 Apache下的当前工作目录将与运行服务器的目录不同,可以是任何目录。

消除明显后的第二次尝试。

pdftk程序是一个Java程序,它依赖于能够生成/接收SIGPWR信号来触发垃圾回收或执行其他操作。问题在于,在守护程序模式下的Apache/mod_wsgi下,信号在请求处理程序线程内被阻止,以确保仅由主线程接收信号,以查找进程关闭触发事件。当您 fork 运行pdftk的进程时,很遗憾,它是从请求处理程序线程继承被阻止的sigmask。其结果是,它阻碍了Java垃圾回收过程的运行,并导致pdftk以奇怪的方式失败。

唯一的解决方案是使用Celery,并使前端将作业提交给Celery队列,让celeryd进行 fork 并执行pdftk。由于此操作是通过不同于Apache创建的进程完成的,因此不会出现此问题。

有关更多信息,请参见Google的mod_wsgi和pdftk,特别是在Google网上论坛中。

http://groups.google.com/group/modwsgi/search?group=modwsgi&q=pdftk&qt_g=Search+this+group

关于python - 在wsgi中如何启动pdftk子进程?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7543452/

10-12 22:47