python - 如何在 wsgi 中启动 pdftk 子进程?

标签 python django subprocess mod-wsgi pdftk

我需要在 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 创建的进程完成的,所以您不会遇到这个问题。

有关 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/

相关文章:

python - 将字符串转换为键不是字符串的字典

python matplotlib : how to automatically save figures in . 图格式?

django-compressor,heroku,s3 : Request has expired

python - 使导航栏项目在 Django 模板中处于事件状态

python - 使用子进程 popen 运行列表命令字符串并获取输出

python - 如何在Python中调试subprocess.call()?

python - 在python3中优雅地退出多进程

python - 使用 numpy 和 sklearn 的 R^2(决定系数)计算给出了不同的结果

python - Django 测试, 'SQLCompiler' 对象没有属性 'col_count'

Python:分割并格式化字符串中的空格分隔值以在 subprocess.check_call 中使用