Python 从 Django 与单元测试调用时子进程的行为不同

Python subprocess behaves different when called from Django vs unit test

我第一次发帖 - 请放轻松。我想不出一个简洁的标题来概括这个问题。我似乎有编解码器问题。

我的 django-based 网站调用子进程 (soffice) 将上传的文档转换为基本文本文件,然后继续对文档中的文本进行一些处理。这有一段时间效果很好。在我的本地开发机器上,文件转换的单元测试仍然和完整的 django 应用程序一样完美运行,end-to-end。在过去一切正常的生产服务器上,文件转换调用在 django 应用程序中的工作方式不再相同,而在测试代码中 运行 时它可以正常工作。此行为变化似乎是 运行ning 常规服务器更新的结果。

args = ['soffice',
        '--headless',
        '--convert-to',
        'txt:Text',
        '--outdir',
        outDir,
        filePath]

subprocess.call(args)

fo = open(textFilePath, "r")

try:
    docText = fo.read()
except:
    print("Failed to read", textFilePath)
    docText = None

我删除了一些错误检查以简化一些操作。

当我 运行 将文件转换代码作为生产服务器上完整 django 应用程序的一部分时,我可以看到某些特殊字符(例如符号 §)变成了垃圾。但是如果我 运行 自己在同一台机器上的 django 之外使用相同的文件转换代码,那么这些符号不会损坏。如前所述,在我的开发机器上,它既可以独立运行,也可以在 django 中运行。两台机器之间的一个区别是我如何 运行 django。在本地,它是 运行 使用 django 的 运行server 命令。在生产机器上,它使用 mod_wsgi 和 apache。我看不出 django 或 mod_wsgi 怎么可能干扰 soffice 在子进程中所做的事情,但它确实是那样的。我在有问题的服务器上打开了一个 python shell 并且 运行 与上面的代码基本相同,得到干净的文本,加上 运行 对其进行单元测试也有效.

真诚感谢任何帮助!

如果您正在使用 mod_wsgi 守护程序模式,请确保您设置的是 lang/locale,否则您将从操作系统继承默认的 ASCII 编码。

这也会传播到子流程。

如果不使用守护进程模式,您真的应该考虑这样做,因为它优于 mod_wsgi 的嵌入式模式。如果使用嵌入式模式,则更改 lang/locale 有点困难,因为必须在 Apache 启动脚本中完成,具体操作方式取决于平台和发行版。

解决方案是升级 mod_wsgi 使用:

pip install mod_wsgi --upgrade