python中路径的跨平台拆分
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4579908/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
cross-platform splitting of path in python
提问by Aaron Yodaiken
I'd like something that has the same effect as this:
我想要一些与此具有相同效果的东西:
>>> path = "/foo/bar/baz/file"
>>> path_split = path.rsplit('/')[1:]
>>> path_split
['foo', 'bar', 'baz', 'file']
But that will work with Windows paths too. I know that there is an os.path.split()but that doesn't do what I want, and I didn't see anything that does.
但这也适用于 Windows 路径。我知道有一个os.path.split()但那不会做我想要的,而且我没有看到任何可以做的事情。
采纳答案by John Machin
The OP specified "will work with Windows paths too". There are a few wrinkles with Windows paths.
OP 指定“也适用于 Windows 路径”。Windows 路径有一些皱纹。
Firstly, Windows has the concept of multiple drives, each with its own current working directory, and 'c:foo'and 'c:\\foo'are often not the same. Consequently it is a very good idea to separate out any drive designator first, using os.path.splitdrive(). Then reassembling the path (if required) can be done correctly by
drive + os.path.join(*other_pieces)
首先,Windows有多个驱动器的概念,每一个都有自己当前的工作目录,'c:foo'而'c:\\foo'往往是不一样的。因此,首先使用 os.path.splitdrive() 分离任何驱动器指示符是一个很好的主意。然后重新组装路径(如果需要)可以通过
drive + os.path.join(*other_pieces)
Secondly, Windows paths can contain slashes or backslashes or a mixture. Consequently, using os.sepwhen parsing an unnormalised path is not useful.
其次,Windows 路径可以包含斜杠或反斜杠或混合。因此,os.sep在解析非规范化路径时使用是没有用的。
More generally:
更普遍:
The results produced for 'foo'and 'foo/'should not be identical.
为'foo'和产生的结果'foo/'不应相同。
The loop termination condition seems to be best expressed as "os.path.split() treated its input as unsplittable".
循环终止条件似乎最好表达为“os.path.split() 将其输入视为不可拆分”。
Here's a suggested solution, with tests, including a comparison with @Spacedman's solution
这是一个建议的解决方案,带有测试,包括与@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
and here's the output (Python 2.7.1, Windows 7 Pro):
这是输出(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
回答by Benjamin Bannier
回答by Kos
Someone said "use os.path.split". This got deleted unfortunately, but it is the right answer.
有人说“用os.path.split”。不幸的是,这被删除了,但这是正确的答案。
os.path.split(path)
Split the pathname path into a pair, (head, tail) where tail is the last pathname component and head is everything leading up to that. The tail part will never contain a slash; if path ends in a slash, tail will be empty. If there is no slash in path, head will be empty. If path is empty, both head and tail are empty. Trailing slashes are stripped from head unless it is the root (one or more slashes only). In all cases, join(head, tail) returns a path to the same location as path (but the strings may differ).
os.path.split(路径)
将路径名路径拆分为一对 (head, tail),其中 tail 是最后一个路径名组件,head 是导致该组件的所有内容。尾部永远不会包含斜线;如果路径以斜杠结尾,则尾部将为空。如果路径中没有斜线,则头部将为空。如果 path 为空,则 head 和 tail 都为空。尾部斜线从头部剥离,除非它是根(只有一个或多个斜线)。在所有情况下,join(head, tail) 都会返回与 path 相同位置的路径(但字符串可能不同)。
So it's not just splitting the dirname and filename. You can apply it several times to get the full path in a portable and correct way. Code sample:
所以这不仅仅是拆分目录名和文件名。您可以多次应用它,以可移植且正确的方式获取完整路径。代码示例:
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
Please credit the original author if that answer gets undeleted.
如果该答案未被删除,请注明原作者。
回答by Glenn Maynard
Use the functionality provided in os.path, e.g.
使用 os.path 中提供的功能,例如
os.path.split(path)
(This answer was by someone else and was mysteriously and incorrectly deleted, since it's a working answer; if you want to split each part of the path apart, you can call it multiple times, and each call will pull a component off of the end.)
(这个答案是别人的,被神秘错误地删除了,因为它是一个有效的答案;如果你想把路径的每一部分分开,你可以多次调用它,每次调用都会从末尾拉出一个组件.)
回答by Spacedman
So keep using os.path.split until you get to what you want. Here's an ugly implementation using an infinite loop:
所以继续使用 os.path.split 直到你得到你想要的。这是一个使用无限循环的丑陋实现:
import os.path
def parts(path):
components = []
while True:
(path,tail) = os.path.split(path)
if tail == "":
components.reverse()
return components
components.append(tail)
Stick that in parts.py, import parts, and voila:
把它放在parts.py 中,导入parts,瞧:
>>> parts.parts("foo/bar/baz/loop")
['foo', 'bar', 'baz', 'loop']
Probably a nicer implementation using generators or recursion out there...
使用生成器或递归可能是一个更好的实现......
回答by anatoly techtonik
One more try with maxplit option, which is a replacement for os.path.split()
再试一次 maxplit 选项,它是 os.path.split() 的替代品
def pathsplit(pathstr, maxsplit=1):
"""split relative path into list"""
path = [pathstr]
while True:
oldpath = path[:]
path[:1] = list(os.path.split(path[0]))
if path[0] == '':
path = path[1:]
elif path[1] == '':
path = path[:1] + path[2:]
if path == oldpath:
return path
if maxsplit is not None and len(path) > maxsplit:
return path
回答by Dave
Here's an explicit implementation of the approach that just iteratively
uses os.path.split; uses a slightly different loop termination condition than the accepted answer.
这是迭代使用的方法的显式实现os.path.split;使用与接受的答案略有不同的循环终止条件。
def splitpath(path):
parts=[]
(path, tail)=os.path.split( path)
while path and tail:
parts.append( tail)
(path,tail)=os.path.split(path)
parts.append( os.path.join(path,tail) )
return map( os.path.normpath, parts)[::-1]
This should satisfy os.path.join( *splitpath(path) )is pathin the sense that they both indicate the same file/directory.
这应该满足的os.path.join( *splitpath(path) )是path它们都指示相同的文件/目录。
Tested in linux:
在 linux 中测试:
In [51]: current='/home/dave/src/python'
In [52]: splitpath(current)
Out[52]: ['/', 'home', 'dave', 'src', 'python']
In [53]: splitpath(current[1:])
Out[53]: ['.', 'dave', 'src', 'python']
In [54]: splitpath( os.path.join(current, 'module.py'))
Out[54]: ['/', 'home', 'dave', 'src', 'python', 'module.py']
In [55]: splitpath( os.path.join(current[1:], 'module.py'))
Out[55]: ['.', 'dave', 'src', 'python', 'module.py']
I hand checked a few of the DOS paths, using the by replacing os.pathwith ntpathmodule, look OK to me, but I'm not too familiar with the ins and outs of DOS paths.
我手动检查了一些 DOS 路径,使用 by 替换os.path为ntpath模块,对我来说还可以,但我对 DOS 路径的来龙去脉不太熟悉。
回答by John Crawford
Python 3.4 introduced a new module pathlib. pathlib.Pathprovides file system related methods, while pathlib.PurePathoperates completely independent of the file system:
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')
You can use PosixPath and WindowsPath explicitly when desired:
您可以在需要时显式使用 PosixPath 和 WindowsPath:
>>> from pathlib import PureWindowsPath, PurePosixPath
>>> PureWindowsPath(path).parts
('\', 'foo', 'bar', 'baz', 'file')
>>> PurePosixPath(path).parts
('/', 'foo', 'bar', 'baz', 'file')
And of course, it works with Windows paths as well:
当然,它也适用于 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')
Huzzah for Python devs constantly improving the language!
Huzzah for Python 开发人员不断改进语言!

