Python subprocess.run()参数编码

Python subprocess.run()参数编码,python,encoding,mod-wsgi,Python,Encoding,Mod Wsgi,我有一个Flask应用程序(Linux、带mod_wsgi的Apache、Python3),它使用一些参数调用shell脚本。当subprocess.run()命令参数中存在任何非ascii字符时,应用程序中会发生以下错误: “ascii”编解码器无法对位置5-6中的字符进行编码:序号不在 射程(128) 我花了很多时间试图修复它 命令行中不存在此类问题,仅在应用程序中存在 整个应用程序的输出是Unicode的,没有任何问题。经过一些研究,我得出结论,问题在于“文件系统编码” 我在run.wsg

我有一个Flask应用程序(Linux、带mod_wsgi的Apache、Python3),它使用一些参数调用shell脚本。当
subprocess.run()
命令参数中存在任何非ascii字符时,应用程序中会发生以下错误:

“ascii”编解码器无法对位置5-6中的字符进行编码:序号不在 射程(128)

我花了很多时间试图修复它

命令行中不存在此类问题,仅在应用程序中存在

整个应用程序的输出是Unicode的,没有任何问题。经过一些研究,我得出结论,问题在于“文件系统编码”

我在
run.wsgi
脚本中添加了一些日志语句。FS编码实际上是“ascii”(命令行中是“utf-8”)

在下一步中,我找到了这篇文章

apachehttpd服务器是在其环境中使用
LANG=C
启动的。尽管在
/etc/sysconfig/httpd
中有警告,我还是将其更改为
C.UTF-8
。这没有帮助,FS编码仍然是“ascii”。然后,我甚至将
sys.getfilesystemencoding()
修补到
lambda:'utf-8'
。但错误仍然存在

每次更改后,我都正确地重新启动了httpd服务

我束手无策

  • 我的问题真的是由FS编码引起的吗
  • 如果是,为什么我尝试将其更改为utf-8失败
  • 最重要的是:我如何解决这个问题
  • 更新1:

    代码段:

        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)
    

    在mod_wsgi的上下文中,您应该确保使用mod_wsgi守护进程模式,并为mod_wsgi守护进程进程组设置lang/locale。有关此处无法重复的更详细解释,请参阅:

      • (回答自己的问题,希望能对他人有所帮助)

        我做了一个简短的测试程序。这就是我发现的:

      • 文件系统编码是关键
      • 猴子修补不起作用。好吧,没关系。无论如何,这是不可接受的解决办法
      • LANG=C.UTF-8
        要求安装区域设置,但它不在我的系统上(使用
        locale-a检查)。但在第二个系统上,它是可行的
      • 我可以显式进行编码,并将字节作为参数之一传递:

        cmdresult = sub.run(
            [SCRIPT, tid, days, name.encode('utf-8')],
            ...
        
      • 这是可行的,但有一个问题需要回答:

        是否符合文件要求

        我能找到的只是:

        args应该是程序参数序列,或者是单个字符串

        我确实把它理解为一个字符串或字符串列表,但实际上它没有指定什么类型的列表。我也通过了和int来看看会发生什么。我得到了这个错误:

        应为str、bytes或os.PathLike对象


        所以我的解决方案似乎很好。

        您是否使用
        shell=True
        进行调用?您是以字符串还是列表的形式传递参数?请显示正在使用
        子流程
        模块的实际代码。在操作系统级别,
        exec()
        和朋友们不关心传递给子流程的参数使用什么编码:POSIX只要求它们可以表示为C
        char*
        字符串,由子进程来解码它们。@DanielPryden Code追加,默认情况下,shell=False。我几天前读了你关于deamon模式的博客,并将从嵌入式模式到守护模式的更改放在了我的列表的首位。谢谢你写这些博客。关于这个问题,我认为它与
        mod\u wsgi
        关系不大。我找到了一个Python解决方案。