在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/