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

2023-11-24

我需要在 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 下创建输出文件。这次讨论似乎表明操作系统信号和 pdftk 可能存在一些我不明白的更深层次的巫术。

是否有任何解决方法可以让这样的子进程调用在 wsgi 下正常工作?我避免使用 PyPDF 来组合 pdf 文件,因为我必须组合足够多的文件(数百个),从而耗尽内存(PyPDF 需要在组合它们时使每个源 pdf 文件在内存中保持打开状态)。

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


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


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

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

唯一的解决方案是使用 Celery 并让前端向 Celery 队列提交作业,以便 celeryd 然后 fork 并执行 pdftk。因为这是通过与 Apache 不同创建的进程完成的,所以您不会遇到此问题。

要了解更多血淋淋的细节,请 Google 搜索 mod_wsgi 和 pdftk,特别是在 Google 网上论坛中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 wsgi 中启动 pdftk 子进程? 的相关文章

随机推荐