跨平台拆分python中的路径

Aar*_*ken 19 python

我想要一些效果与此相同的东西:

>>> path = "/foo/bar/baz/file"
>>> path_split = path.rsplit('/')[1:]
>>> path_split
['foo', 'bar', 'baz', 'file']
Run Code Online (Sandbox Code Playgroud)

但这也适用于Windows路径.我知道有一个os.path.split()但是没有做我想做的事情,我没有看到任何事情.

Joh*_*ord 27

Python 3.4引入了一个新模块pathlib. pathlib.Path提供与文件系统相关的方法,同时pathlib.PurePath完全独立于文件系统运行:

>>> from pathlib import PurePath
>>> path = "/foo/bar/baz/file"
>>> path_split = PurePath(path).parts
>>> path_split
('\\', 'foo', 'bar', 'baz', 'file')
Run Code Online (Sandbox Code Playgroud)

您可以在需要时显式使用PosixPath和WindowsPath:

>>> from pathlib import PureWindowsPath, PurePosixPath
>>> PureWindowsPath(path).parts
('\\', 'foo', 'bar', 'baz', 'file')
>>> PurePosixPath(path).parts
('/', 'foo', 'bar', 'baz', 'file')
Run Code Online (Sandbox Code Playgroud)

当然,它也适用于Windows路径:

>>> wpath = r"C:\foo\bar\baz\file"
>>> PurePath(wpath).parts
('C:\\', 'foo', 'bar', 'baz', 'file')
>>> PureWindowsPath(wpath).parts
('C:\\', 'foo', 'bar', 'baz', 'file')
>>> PurePosixPath(wpath).parts
('C:\\foo\\bar\\baz\\file',)
>>>
>>> wpath = r"C:\foo/bar/baz/file"
>>> PurePath(wpath).parts
('C:\\', 'foo', 'bar', 'baz', 'file')
>>> PureWindowsPath(wpath).parts
('C:\\', 'foo', 'bar', 'baz', 'file')
>>> PurePosixPath(wpath).parts
('C:\\foo', 'bar', 'baz', 'file')
Run Code Online (Sandbox Code Playgroud)

Huzzah for Python开发人员不断改进语言!

  • @ user966588:这完全没问题,只需运行`pip install pathlib`即可 (4认同)
  • [pathlib的backport(名为pathlib2)在这里](https://pypi.python.org/pypi/pathlib2/). (3认同)

Joh*_*hin 20

OP指定"也适用于Windows路径".Windows路径有一些皱纹.

首先,Windows有多个驱动器的概念,每一个都有自己当前的工作目录,'c:foo''c:\\foo'往往是不一样的.因此,首先使用os.path.splitdrive()分离出任何驱动器指示符是一个非常好的主意.然后可以正确地重新组装路径(如果需要) drive + os.path.join(*other_pieces)

其次,Windows路径可以包含斜杠或反斜杠或混合.因此,os.sep在解析非规范化路径时使用是没有用的.

更普遍:

对所产生的结果'foo''foo/'不应该是相同的.

循环终止条件似乎最好表示为"os.path.split()将其输入视为不可分割".

这是一个建议的解决方案,包括测试,包括与@Spacedman解决方案的比较

import os.path

def os_path_split_asunder(path, debug=False):
    parts = []
    while True:
        newpath, tail = os.path.split(path)
        if debug: print repr(path), (newpath, tail)
        if newpath == path:
            assert not tail
            if path: parts.append(path)
            break
        parts.append(tail)
        path = newpath
    parts.reverse()
    return parts

def spacedman_parts(path):
    components = [] 
    while True:
        (path,tail) = os.path.split(path)
        if not tail:
            return components
        components.insert(0,tail)

if __name__ == "__main__":
    tests = [
        '',
        'foo',
        'foo/',
        'foo\\',
        '/foo',
        '\\foo',
        'foo/bar',
        '/',
        'c:',
        'c:/',
        'c:foo',
        'c:/foo',
        'c:/users/john/foo.txt',
        '/users/john/foo.txt',
        'foo/bar/baz/loop',
        'foo/bar/baz/',
        '//hostname/foo/bar.txt',
        ]
    for i, test in enumerate(tests):
        print "\nTest %d: %r" % (i, test)
        drive, path = os.path.splitdrive(test)
        print 'drive, path', repr(drive), repr(path)
        a = os_path_split_asunder(path)
        b = spacedman_parts(path)
        print "a ... %r" % a
        print "b ... %r" % b
        print a == b
Run Code Online (Sandbox Code Playgroud)

这是输出(Python 2.7.1,Windows 7 Pro):

Test 0: ''
drive, path '' ''
a ... []
b ... []
True

Test 1: 'foo'
drive, path '' 'foo'
a ... ['foo']
b ... ['foo']
True

Test 2: 'foo/'
drive, path '' 'foo/'
a ... ['foo', '']
b ... []
False

Test 3: 'foo\\'
drive, path '' 'foo\\'
a ... ['foo', '']
b ... []
False

Test 4: '/foo'
drive, path '' '/foo'
a ... ['/', 'foo']
b ... ['foo']
False

Test 5: '\\foo'
drive, path '' '\\foo'
a ... ['\\', 'foo']
b ... ['foo']
False

Test 6: 'foo/bar'
drive, path '' 'foo/bar'
a ... ['foo', 'bar']
b ... ['foo', 'bar']
True

Test 7: '/'
drive, path '' '/'
a ... ['/']
b ... []
False

Test 8: 'c:'
drive, path 'c:' ''
a ... []
b ... []
True

Test 9: 'c:/'
drive, path 'c:' '/'
a ... ['/']
b ... []
False

Test 10: 'c:foo'
drive, path 'c:' 'foo'
a ... ['foo']
b ... ['foo']
True

Test 11: 'c:/foo'
drive, path 'c:' '/foo'
a ... ['/', 'foo']
b ... ['foo']
False

Test 12: 'c:/users/john/foo.txt'
drive, path 'c:' '/users/john/foo.txt'
a ... ['/', 'users', 'john', 'foo.txt']
b ... ['users', 'john', 'foo.txt']
False

Test 13: '/users/john/foo.txt'
drive, path '' '/users/john/foo.txt'
a ... ['/', 'users', 'john', 'foo.txt']
b ... ['users', 'john', 'foo.txt']
False

Test 14: 'foo/bar/baz/loop'
drive, path '' 'foo/bar/baz/loop'
a ... ['foo', 'bar', 'baz', 'loop']
b ... ['foo', 'bar', 'baz', 'loop']
True

Test 15: 'foo/bar/baz/'
drive, path '' 'foo/bar/baz/'
a ... ['foo', 'bar', 'baz', '']
b ... []
False

Test 16: '//hostname/foo/bar.txt'
drive, path '' '//hostname/foo/bar.txt'
a ... ['//', 'hostname', 'foo', 'bar.txt']
b ... ['hostname', 'foo', 'bar.txt']
False
Run Code Online (Sandbox Code Playgroud)


Kos*_*Kos 19

有人说"用os.path.split".不幸的是,这被删除了,但这是正确的答案.

os.path.split这样的(路径)

将路径名路径拆分为一对(头部,尾部),其中tail是最后一个路径名组件,head是指向该路径的所有内容.尾部永远不会有斜线; 如果path以斜线结尾,则tail将为空.如果路径中没有斜杠,则head将为空.如果path为空,则head和tail都为空.尾部斜杠从头部剥离,除非它是根(仅一个或多个斜杠).在所有情况下,join(head,tail)返回与path相同位置的路径(但字符串可能不同).

所以它不只是拆分目录名和文件名.您可以多次应用它以便携式和正确的方式获得完整路径.代码示例:

dirname = path
path_split = []
while True:
    dirname, leaf = split(dirname)
    if leaf:
        path_split = [leaf] + path_split #Adds one element, at the beginning of the list
    else:
        #Uncomment the following line to have also the drive, in the format "Z:\"
        #path_split = [dirname] + path_split 
        break
Run Code Online (Sandbox Code Playgroud)

如果答案取消删除,请将原作者归功于原创作者.

  • +1:只需使用正确的库函数,正确的方法就是最好的解决方案. (2认同)

Ben*_*ier 5

使用中提供的功能os.path,例如

os.path.split(path)
Run Code Online (Sandbox Code Playgroud)

就像其他地方写的那样,您可以多次调用它来分割更长的路径。