【问题标题】:when is it "safe" to mix path separators in Python strings representing Windows paths?什么时候在表示 Windows 路径的 Python 字符串中混合路径分隔符是“安全的”?
【发布时间】:2023-02-23 09:49:00
【问题描述】:

这个最小的例子:(在 PyCharm 调试器中运行)

import os
from os.path import join
import subprocess

src_path = r'C:/TEMP/source'
dest_path = r'C:/TEMP/dest'


if __name__ == "__main__":
    for root, _, files in os.walk(src_path):
        for name in files:
            src_file_path = join(root, name)
            rel_dest_file_path = os.path.join(dest_path, os.path.dirname(os.path.relpath(src_file_path, src_path)))
            rdfp = join(rel_dest_file_path, name)
            sfp = src_file_path
            cmd = "['copy', '/v', %s, %s]" % (sfp, rdfp)
            print 'calling shell subprocess %s' % cmd
            subprocess.call(['copy', '/v', sfp, rdfp], shell=True)

产生这个输出:

calling shell subprocess ['copy', '/v', C:/TEMP/source\foo bar.txt, C:/TEMP/dest\foo bar.txt]
1 file(s) copied.
calling shell subprocess ['copy', '/v', C:/TEMP/source\foo.txt, C:/TEMP/dest\foo.txt]
The syntax of the command is incorrect.

Process finished with exit code 0

为什么名为“foo bar.txt”的文件的路径不会产生命令语法错误?为什么路径反而导致成功的文件复制?

我可以通过在初始原始字符串文字路径分配中显式使用 Windows 路径分隔符来修复示例中的语法问题,这对我来说很有意义。

src_path = r'C:\TEMP\source'
dest_path = r'C:\TEMP\dest'

没有意义的是为什么“混合斜杠”路径中的空格也“解决”了语法问题。

任何参考或指针?

【问题讨论】:

  • 您使用 2.x 是否有特殊原因,它已超过其生命周期终止日期 3 年以上?无论如何,这似乎真的是一个关于 Windows 本身的问题,而不是关于编写 Python 代码的问题。

标签: python windows shell path-separator


【解决方案1】:

简短的回答:保持一致,始终使用操作系统首选的分隔符。不要依赖偶然发生的情况来保护你。

您的具体案例的解释:在 Windows 上,程序是使用单个字符串启动的,而不是像 POSIX 系统上那样的参数向量。您将 list 作为命令传递,这意味着它必须转换为单个字符串。 Python 使用内部函数 list2cmdline 来完成此操作。它在空参数周围添加引号,以及任何包含空格或制表符的参数。因此,您的代码仅在有空格时才引用路径:

>>> print(subprocess.list2cmdline(['copy', '/v', r"C:/TEMP/sourceoo bar.txt", r"C:/TEMP/destoo bar.txt"]))
copy /v "C:/TEMP/sourceoo bar.txt" "C:/TEMP/destoo bar.txt"

>>> print(subprocess.list2cmdline(['copy', '/v', r"C:/TEMP/sourceoo.txt", r"C:/TEMP/destoo.txt"]))
copy /v C:/TEMP/sourceoo.txt C:/TEMP/destoo.txt

看起来 copy 的参数解析对于路径中的反斜杠是可以的,如果路径被引用,但没有被引用,它会变得混乱(可能是因为解析器将不受保护的正斜杠视为引入了奇怪的开关)。

这里更通用的规则是 WinAPI 调用可以使用混合分隔符,但个别程序的参数解析可能不行。但是同样,首先通过使用os.path.join、os.sep、Path对象的/重载等来跳过问题,而不是对路径进行硬编码(除非路径受操作系统限制以至于它们可以在不匹配的操作系统上不存在,例如在你的情况下,你在 Windows 上,只有 Windows 路径,并且应该只使用带反斜杠的原始字符串文字)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-06
    • 2011-10-19
    • 1970-01-01
    • 2018-11-17
    • 1970-01-01
    • 2014-07-29
    相关资源
    最近更新 更多