Windows 上的目录参数在传递给 Python 时将尾部反斜杠替换为双引号

Directory parameter on Windows has trailing backslash replaced with double quote when passed to Python

我在将 Windows 中的引用目录传递到 Python 时看到一个烦人的尾随双引号。

这是我的Python测试程序,print_args.py:

import sys
print(sys.argv)

这是我从命令行 运行 得到的结果。注意引用的目录是Windowsshell中tab补全生成的标准格式。由于路径中的空格,需要双引号。

>py print_args.py -test "C:\Documents and Settings\"
['print_args.py', '-test', 'C:\Documents and Settings"']

结尾的反斜杠已替换为双引号,大概是因为 Python 将其读作带引号的双引号,而不是将其与前导引号匹配。

如果我没有将参数传递给 Python,而是将它传递给一个批处理脚本,它只是回应它,那么我得到了预期的尾部反斜杠。

所以在 CMD shell 和 Python 之间的某处看到 sys.argv 有一些解析影响了反斜杠和双引号。

谁能照亮一下?

编辑添加:

进一步阅读表明 Python 正在对 windows 命令行参数进行一些解析以构造 sys.argv。我认为 Windows 将整个命令行字符串(在本例中大部分未更改)传递给 Python 并且 Python 使用其自己的内部逻辑将其分解为 sys.argv 中的字符串列表。作为一种特殊情况,此处理必须允许转义双引号。我很高兴看到一些文档或代码...

您需要转义反斜杠,因为反斜杠本身就是 Python 和 PowerShell 的转义字符。否则,\" 意味着传入一个 " 文字而不是用它来包围字符串。以下对我来说很好用:

PS> py print_args.py -test "C:\Documents and Settings\"

输出:

['rando.py', '-test', 'C:\Documents and Settings\']

Windows 上的命令行处理尚未完全标准化,但在 Python 和许多其他程序的情况下,它使用 Microsoft C 运行时行为。这是指定的,例如 here。它说

A string surrounded by double quote marks is interpreted as a single argument, which may contain white-space characters. [...] If the command line ends before a closing double quote mark is found, then all the characters read so far are output as the last argument.

A double quote mark preceded by a backslash (") is interpreted as a literal double quote mark (").

这两条规则中的第二条规则防止第二个双引号被读取为终止参数 - 而是附加一个双引号。然后第一条规则允许参数结束时没有终止双引号。

注意这部分还说

The command line parsing rules used by Microsoft C/C++ code are Microsoft-specific.

这在使用 PowerShell 时更加令人困惑。

PS> py print_args.py -test 'C:\Documents and Settings\'
['print_args.py', '-test', 'C:\Documents and Settings"']

此处 PowerShell 解析保留了最后的反斜杠并删除了单引号。然后它在将命令行传递给 C 运行时之前添加双引号(因为路径中有空格),C 运行时根据规则对其进行解析,转义 PowerShell 添加的双引号。

然而,这一切都符合记录的行为,并不是错误。