【问题标题】:append to list function encodes german umlauts wrong附加到列表函数编码德语变音符号错误
【发布时间】:2018-09-10 08:14:33
【问题描述】:

我想遍历文件夹中的一些文件并将文件的路径发送到列表。然后我想将此列表传递给子进程以执行 bash 命令:

procfiles = []
os.chdir("/path/to/directory")

for root, dirs, files in os.walk('.'):
    for file in files:
        if '.mp3' in file:
            filename = os.path.join(root, file)
            print(filename)
            procfiles.append(filename)
print(procfiles)

args = [command, with, arguments].extend(procfiles)
process = subprocess.Popen(args, shell=False)
output, error = process.communicate()

但是当文件包含德语变音字母时,我得到以下输出。例如:ä、ö 或 ü

./titleWith ä or ü - artist with ü.mp3                                         #print(filename)
['./titleWith \udcc3\udca4 or \udcc3\udcbc - artist with \udcc3\udcbc.mp3']    #print(procfiles)

这意味着在编码过程中出现了问题 procfiles.append(filename) 进程,对吧?

之后子进程失败并出现错误:

UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc3' in 位置 43:不允许代理

信息:

  • Python 3.5.3
  • 操作系统:Debian Jessie
  • 内核:4.9.58+
  • 架构:armhf

更新:

我刚刚注意到,当我使用用户 rootwww-data 手动执行它时,它可以工作,但是当我通过我的 custom php 执行它时脚本(它只是一个shell_exec('/usr/bin/python3 /path/to/script.py >> /path/to/log.log 2>&1'))它不起作用。

这不应该和我从用户 www-data 手动执行它时一样吗?还是在从 php 脚本执行 python 脚本时设置了其他一些环境变量?

【问题讨论】:

    标签: python python-3.x subprocess


    【解决方案1】:

    Python3.5

    首先转换你的字符串:

    procfiles = [s.encode('utf-8', errors='surrogateescape').decode('utf-8')
                 for s in procfiles]
    

    Python 3.6

    您可以使用errors='surrogateescape' 指定忽略此错误:

    process = subprocess.Popen(args, shell=False, errors='surrogateescape')
    

    【讨论】:

    • with errors='surrogateescape' 我得到错误:TypeError: __init__() got an unexpected keyword argument 'errors' 我猜你的意思是来自解码或编码的参数,如here 所述。在将其传递给子流程之前,我是否必须对其进行解码或编码?
    • 上升。我使用了 Python 3.6,它有这个关键字参数。 Python 3.5 没有。
    • 更新了我的答案。
    【解决方案2】:

    如果我运行这个脚本:

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import os
    import subprocess
    
    procfiles = []
    os.chdir("/home/dede/tmp/")
    
    for root, dirs, files in os.walk('.'):
        for file in files:
            if '.mp3' in file:
                filename = os.path.join(root, file)
                print(filename)
                procfiles.append(filename)
    print(procfiles)
    
    args=["ls", "-la"]
    args.extend(procfiles)
    process = subprocess.Popen(args, shell=False)
    output, error = process.communicate()
    

    我得到这个输出:

    dede@i5:~> python3 tst.py 
    ./Leere Datei.mp3
    ./Kopie ä  von Leere Datei.mp3
    ['./Leere Datei.mp3', './Kopie ä  von Leere Datei.mp3']
    -rw-r--r-- 1 dede users 6 31. Mär 16:50 ./Kopie ä  von Leere Datei.mp3
    -rw-r--r-- 1 dede users 6 31. Mär 16:50 ./Leere Datei.mp3
    

    所以 wrong 部分必须在您的代码中的其他位置....

    ...或者您的 mp3 在 Windows 编码中有它们的 元音变音

    【讨论】:

    • 我只是注意到,当我使用用户 root 或 www-data 手动执行它时,它可以工作,但是当我通过我的自定义 php 脚本(它只有一个 shell_exec('/usr/bin/python3 /path/to/script.py >> /path/to/log.log 2>&1'))执行它时,它没有不工作。这不应该与我从用户 www-data 手动执行它时相同吗?还是在从 php 脚本执行 python 脚本时设置了其他一些环境变量?
    【解决方案3】:

    这正是预期的行为,尽管在您的情况下文件系统编码错误,因此它输出代理转义以正确重新编码您的字符串。 反斜杠转义只是字符串的精确表示。 如果您想正确打印字符(尽管这取决于您的 sys.stdout 和终端的编码),然后在每个字符串上调用 print()。似乎子进程没有将errors=surrogateescape 传递给str.encode()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 2021-07-08
      • 1970-01-01
      • 2016-06-16
      • 2020-12-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多