我有一个Flask应用程序(Linux,带有mod_wsgi的Apache,Python 3),它使用一些参数调用shell脚本。当subprocess.run()
命令参数中存在任何非ascii字符时,应用程序中会出现以下错误:
' ASCII'编解码器不能编码5-6位的字符:序数不在 范围(128)
我花了很多时间试图修复它。
命令行中不存在此类问题,仅在应用程序中存在。
整个应用程序的输出都是Unicode格式,没有任何问题。经过一些研究后,我得出结论,问题在于"文件系统编码"。
我在我的run.wsgi
脚本中添加了一些日志记录语句。 FS编码是' ascii'确实(和命令行中的' utf-8')。
在下一步中,我发现了这篇文章 How to change file system encoding via python?
Apache httpd服务器在其环境中以LANG=C
启动。尽管C.UTF-8
发出了警告,我已将其更改为/etc/sysconfig/httpd
。这没有帮助,FS编码仍然是' ascii'。然后,我甚至将sys.getfilesystemencoding()
修改为lambda: 'utf-8'
。但错误仍然存在。
每次更改后我都已正确重启httpd服务。
我在我的智慧'端。
UPDATE1:
代码段:
import subprocess as sub
cmdresult = sub.run(
[SCRIPT, tid, days, name],
stdin=sub.DEVNULL, stdout=sub.PIPE, stderr=sub.DEVNULL,
encoding='ascii', # 'utf-8' will not help, this affects stdin, stdout I/O only
check=True)
答案 0 :(得分:0)
在mod_wsgi的上下文中,您应确保使用mod_wsgi守护程序模式并为mod_wsgi守护程序进程组设置lang / locale。有关更详细的说明,请在此处重复,请参阅:
答案 1 :(得分:0)
(回答自己的问题,希望它对别人有帮助)
我做了一个简短的测试程序。这是我发现的:
LANG=C.UTF-8
需要安装区域设置,并且它不在我的系统上(使用locale -a
检查)。但是在第二个可用的系统上,它可以工作。我可以明确地进行编码并将字节作为args之一传递:
cmdresult = sub.run(
[SCRIPT, tid, days, name.encode('utf-8')],
...
这是有效的,但有一个问题再次出现:
是否符合文档?
我能找到的只有:
args应该是程序参数序列或者是单个字符串
我确实把它理解为一个字符串或一个字符串列表,但实际上并没有指定哪些类型的列表。我也通过了int来看看会发生什么。我收到了这个错误:
expected str, bytes or os.PathLike object
所以我的解决方案似乎很好。