【问题标题】:mixed slashes with os.path.join on windows在 Windows 上使用 os.path.join 混合斜线
【发布时间】:2013-05-02 08:31:53
【问题描述】:

我倾向于只对路径('/')使用正斜杠,python 也对它在 Windows 上很满意。 在 os.path.join 的描述中,如果你想跨平台,这是正确的方法。但是当我使用它时,我得到了混合斜线:

import os

a = 'c:/'
b = 'myFirstDirectory/'
c = 'mySecondDirectory'
d = 'myThirdDirectory'
e = 'myExecutable.exe'


print os.path.join(a, b, c, d, e)

# Result:
c:/myFirstDirectory/mySecondDirectory\myThirdDirectory\myExecutable.exe

这是正确的吗?我应该以后检查并纠正它还是有更好的方法?

谢谢

编辑: 在询问路径时,我也会得到混合斜线

import sys
for item in sys.path:
    print item

# Result:
C:\Program Files\Autodesk\Maya2013.5\bin
C:\Program Files\Autodesk\Maya2013.5\mentalray\scripts\AETemplates
C:\Program Files\Autodesk\Maya2013.5\Python
C:\Program Files\Autodesk\Maya2013.5\Python\lib\site-packages
C:\Program Files\Autodesk\Maya2013.5\bin\python26.zip\lib-tk
C:/Users/nookie/Documents/maya/2013.5-x64/prefs/scripts
C:/Users/nookie/Documents/maya/2013.5-x64/scripts
C:/Users/nookie/Documents/maya/scripts
C:\Program Files\Nuke7.0v4\lib\site-packages
C:\Program Files\Nuke7.0v4/plugins/modules

【问题讨论】:

  • os 很聪明,可以计算出您的操作系统需要哪些斜线。要正确使用它,请不要在字符串 a、b、c、d 和 e 中添加斜杠 - os 会添加它们。
  • 我明白了,但是如果我在询问路径时得到混合斜线怎么办? (我已经用一个例子更新了第一篇文章)
  • 您可以使用os.path.normpath(mixed_slashes_path) 并使斜线标准化。哦,我猜你是在 Maya 内部做的;它做的事情非常类似于 UNIX,因此它为您添加的路径中的斜线。

标签: python windows path


【解决方案1】:

您可以在path.join() 之后使用.replace() 以确保斜线正确:

# .replace() all backslashes with forwardslashes
print os.path.join(a, b, c, d, e).replace("\\","/")

这给出了输出:

c:/myFirstDirectory/mySecondDirectory/myThirdDirectory/myExecutable.exe

正如@sharpcloud 建议的那样,最好从输入字符串中删除斜杠,但这是一种替代方法。

【讨论】:

  • 最好只导入 posixpath 而不是 os.path 然后执行posixpath.join(a, b, c, d, e) ,这总是会给你正斜杠。
  • @semicolon,posixpath和导入os.path不一样吗?无论如何,在我的 Windows 机器上 posixpath.join() 仍然返回混合斜线。
  • 如果您查看here,os.path 将根据您的操作系统导入 posixpath、ntpath、macpath 或 os2emxpath 之一。我很惊讶您仍然会使用 posixpath 混合斜线。我刚刚在 Windows 机器上测试了它,os.path.join('foo', 'bar') 给了我'a\\b'posixpath.join('foo', 'bar') 给了我'a/b'
  • 我应该澄清os.path.join()(以及它导入的模块)不会替换它正在连接的字符串中的斜杠,这可能会导致混合斜杠(就像问题中发生的那样)。
  • 这是真的,但似乎它加入的字符串中唯一现有的斜杠是正斜杠,并且由于 posixpath 也使用正斜杠,因此在 OP 中使用 posixpath 不会得到任何混合斜杠场景。
【解决方案2】:

您现在自己提供一些斜线并让os.path.join 选择其他斜线。最好让python全部挑选或者自己提供。 Python 在路径的后半部分使用反斜杠,因为反斜杠是 Windows 的默认设置。

import os

a = 'c:' # removed slash
b = 'myFirstDirectory' # removed slash
c = 'mySecondDirectory'
d = 'myThirdDirectory'
e = 'myExecutable.exe'

print os.path.join(a + os.sep, b, c, d, e)

我没有对此进行测试,但我希望这会有所帮助。更常见的是有一个基本路径并且只需要加入一个其他元素,主要是文件。

顺便说一句;您可以使用os.sep 来为运行python 的操作系统设置最佳分隔符。

编辑: 就像破折号一样,显然对于 Windows,您确实需要为路径的根添加一个分隔符。否则,您将创建相对路径而不是绝对路径。

【讨论】:

  • 感谢您的回答,但如果我在一个字符串中出现斜杠(当有两个或多个文件夹时)怎么办?我已经用我从 sys.path 获得的一些路径更新了第一篇文章
  • 这取决于该路径的来源。但大多数时候,你应该已经有了正确格式的斜线。也就是说,如果您通过 Python 获得路径。如果您有一些您无法控制的外部源,并且该源提供正斜杠而不是反斜杠;你可能想先解决这个问题。
  • 所以我应该在之后检查字符串并确保格式正确?
  • 不,我会检查您的外部输入(您显然无法控制其格式的输入) 将其放入os.path.join。这样您就可以确保 os.path.join 不会根据可能的错误输入做出错误的决定。
  • 拆分根目录并重新加入不会产生正确的结果;需要指定C: 的根。见stackoverflow.com/questions/2422798
【解决方案3】:

尝试使用 abspath(使用 python 3)

import os

a = 'c:/'
b = 'myFirstDirectory/'
c = 'mySecondDirectory'
d = 'myThirdDirectory'
e = 'myExecutable.exe'


print(os.path.abspath(os.path.join(a, b, c, d, e)))

输出:

c:\myFirstDirectory\mySecondDirectory\myThirdDirectory\myExecutable.exe

Process finished with exit code 0

【讨论】:

  • os.path.abspath() 首先调用os.path.normpath()。您可以在这里实现相同的目标,只需致电os.path.normpath()
  • 问题仍然存在,因为 Windows 无法正确处理反斜杠并认为它是转义字符。
【解决方案4】:

根据评论编辑: path = os.path.normpath(path)

我之前的回答缺乏处理转义字符的能力,因此不应该使用

  • 首先,将路径转换为文件夹和文件名数组。
  • 其次,使用正确的符号将它们粘在一起。

    import os   
    path = 'c:\www\app\my/folder/file.php'
    # split the path to parts by either slash symbol:
    path = re.compile(r"[\/]").split(path)
    # join the path using the correct slash symbol:
    path = os.path.join(*path)
    

【讨论】:

  • 请注意,如果您的字符串碰巧使用 ` \ ` 转义文件夹内的空格,此方法将中断。例如"/usr/my\ files" 将转换为"usr","my"," files" 而不是"usr","my files"
  • 不要重新发明轮子。只需使用os.path.normpath()
【解决方案5】:

如果出于任何原因您需要自己提供路径并且您使用了高于 python 3.4 的任何内容,您可以使用pathlib

from pathlib import Path, PurePosixPath

a = PurePosixPath('c:/')
b = PurePosixPath('myFirstDirectory/')
c = 'mySecondDirectory'
d = 'myThirdDirectory'
e = 'myExecutable.exe'

print(a / b / c / d / e)

# Result
c:/myFirstDirectory/mySecondDirectory/myThirdDirectory/myExecutable.exe

当我需要用户提供资产目录的位置并且我的代码正在使用 Windows 路径字符串查找时,我使用了它

In [1]: from pathlib import Path, PureWindowsPath
In [2]: USER_ASSETS_DIR = Path('/asset/dir') # user provides this form environment variable
In [3]: SPECIFIC_ASSET = PureWindowsPath('some\\asset')
In [4]: USER_ASSETS_DIR / SPECIFIC_ASSET

Out[4]: PosixPath('/asset/dir/some/asset')

【讨论】:

    【解决方案6】:

    os 为您添加斜线并确保不要重复斜线,因此请在您的字符串中省略它们

    import os
    
    # Don't add your own slashes
    a = 'C:'
    b = 'myFirstDirectory' 
    c = 'mySecondDirectory'
    d = 'myThirdDirectory'
    e = 'myExecutable.exe'
    
    print os.path.join(a, b, c, d, e)
    C:\myFirstDirectory\mySecondDirectory\myThirdDirectory\myExecutable.exe
    

    补充:

    我不确定您为什么在 sys 路径中混合了斜杠(您是否使用过 linux 操作系统来添加一些文件夹?)但请尝试检查

    print os.path.isdir(os.path.join('C:','Users','nookie')).

    如果这是True,那么os 适用于您的混合斜线。

    无论哪种方式,我都会避免将目录名称硬编码到您的程序中。您的 sys.path for 循环是提取这些目录的安全方法。然后,您可以使用一些字符串方法或正则表达式来选择所需的文件夹。

    【讨论】:

    • os.path.isdir(os.path.join('C:','Users','nookie')) 返回 False。我没有使用任何 Linux 操作系统来添加我的文件夹,那些只是来自软件安装!
    • 你使用的是什么版本的 Python,@ejrb?因为在我的,我没有得到第一个斜线。 (我看到C:myFirstDirectory\mySecondDirectory...
    【解决方案7】:

    Postgres 命令客户端 psql 即使在 Windows 上也不接受反斜杠:

    >psql -U user -h 111.111.111.111 -d mydb
    psql (12.2, server 12.5 . . .
    . . .
    mydb=> \i C:\my\path\myscript.sql
    C:: Permission denied
    

    所以在从Python 3.8.6 执行时需要修复它。不想诉诸简单的字符串替换并使用现有功能:

    script_path = Path(script_dir).resolve()
    input_sql = f'\\i {script_path.joinpath("myscript.sql").as_posix()}\n'
    

    但实际上它有:

    # ...\Programs\Python\Python38\Lib\pathlib.py
        def as_posix(self):
            """Return the string representation of the path with forward (/)
            slashes."""
            f = self._flavour
            return str(self).replace(f.sep, '/')
    

    【讨论】:

      【解决方案8】:

      您也可以这样做:

      import re
      
      a = 'c:/'
      b = 'myFirstDirectory/'
      c = 'mySecondDirectory'
      d = 'myThirdDirectory'
      e = 'myExecutable.exe'
      
      joined = os.path.join(a, b, c, d, e)
      formatted = re.sub(r'/|\\', re.escape(os.sep), joined)
      

      这会将所有可能混合的斜杠转换为符合操作系统的斜杠。

      我知道这是一个古老的话题,但我无法抗拒。 :)

      【讨论】:

        【解决方案9】:

        我这样做的方式相当简单:rstrip 从斜线开始的所有路径,无论数量和正确性如何,使用正确的分隔符将这些路径添加回来。

        import os
        
        def join_path_regardless_of_separators(*paths):
            return os.path.sep.join(path.rstrip(r"\/") for path in paths)
         
        a = 'c:/'
        b = 'myFirstDirectory/'
        c = 'mySecondDirectory'
        d = 'myThirdDirectory\\\\\\/'
        e = 'myExecutable.exe'
        join_path_regardless_of_separators(a, b, c, d, e)
        >>> 'c:\\myFirstDirectory\\mySecondDirectory\\myThirdDirectory\\myExecutable.exe'
        

        另一种使用方式,结果相同:

        join_path_regardless_of_separators(*"""c:////\\\\
                                               myFirstDirectory/
                                               mySecondDirectory\\\\
                                               myThirdDirectory/////
                                               myExecutable.exe
                                            """.split())
        

        【讨论】:

          猜你喜欢
          • 2021-08-18
          • 2011-01-26
          • 1970-01-01
          • 1970-01-01
          • 2018-03-22
          • 1970-01-01
          • 2021-03-31
          • 1970-01-01
          • 2010-09-29
          相关资源
          最近更新 更多