我非常喜欢一组文件名组件,它们会在Windows和Cygwin上为我提供一致且“漂亮”的文件名。这是我尝试过的:
Input Windows Cygwin
1 os.path.join('c:', 'foo', 'bar') c:foo\bar c:/foo/bar
2 os.path.join('c:\\', 'foo', 'bar') c:\foo\bar c:\/foo/bar
3 os.path.join('c:/', 'foo', 'bar') c:/foo\bar c:/foo/bar
1不是我想要的Windows,我想要一个绝对路径,而不是相对于当前目录。
2和3都可以工作,但不是(我在此定义)“漂亮”,因为它们在一个平台或另一个平台上混合了向前和向后斜线。如果我可以避免这种情况,我的错误和日志消息将更具可读性。
选项4是在Windows上定义driveroot
变量等于c:\
,在Cygwin上定义/cygdrive/c
。或者是一个带驱动器号并返回相同功能的功能。但我也更愿意避免这两者之间的每个平台特殊情况。
我可以拥有我想要的一切(加入相同的路径组件,在两个平台上提供引用相同绝对路径的结果,并且不在任何平台上混合路径分隔符)?或者我必须在某处妥协?
[编辑:如果有帮助,主要用例是c:\foo
是我在配置时知道的路径,而bar
(以及其他组件)稍后计算。所以我的实际代码目前看起来更像这样:
dir = os.path.join('c:\\', 'foo')
# some time later
os.path.join(dir, 'bar')
这是使用选项2,这导致Windows中文件名的“很好”报告,但在Cygwin中报告文件名“不好”。如果可能的话,我想避免的是:
if this_is_cygwin():
dir = '/cygdrive/c/foo'
else:
dir = 'c:\\foo'
答案 0 :(得分:4)
编辑:David指出我对Windows上“当前目录”的理解是错误的。抱歉。但是,尝试使用os.path.abspath
来获得漂亮的漂亮路径,或者os.path.normpath
如果您不需要绝对路径。
在方法1中,
os.path.join('c:', 'foo', 'bar')
输出c:foo\bar
是正确的。这意味着foo\bar
上当前目录下面的路径c:
,这与根目录不同。 os.path.join
正在按照您的意思执行操作,即将c:
(驱动器c上的当前目录)并添加一些额外的位。
在方法2中,
os.path.join(r'c:\', 'foo', 'bar')
Cygwin的输出是正确的,因为在Cygwin中,c:\
不是驱动器的根。
你想要的是os.abspath
功能。这将为您提供您提供给它的路径的绝对标准化版本。
但是:您不会在Cygwin和Windows上获得相同的字符串。我希望你不是在寻找那个。
答案 1 :(得分:-1)
在工作中,我必须处理没有Cygiwn的Windows的随机组合,非Cygwin Python的Cygwin,Cygwin Python的Cygwin和Unix。我还没有找到一种方法来应对这些我特别自豪的东西,但到目前为止我发现的最不可靠的方法是始终使用Cygwin所谓的Windows上的“混合风格”路径。这是一个Windows风格的路径,但使用正斜杠而不是反斜杠。例如,c:/foo/bar.txt。它还避免了很多陷阱,例如Cygwin bash shell将“\”视为转义字符。遗憾的是,这意味着错过了很多Python的内置路径操作实用程序并且很难做到。
我无法访问ATM上的Python和Cygwin机器,所以我无法测试下面的代码片段。我为任何错误道歉...
#Combine a path
path = '/'.join([ 'c:', 'foo', 'bar'])
#Split it back apart
pieces = path.split('/')
如有疑问,请尝试调用Cygwin的cygpath实用程序。在Cygwin中出现了许多奇怪的边缘情况,例如/ cygdrive / d / == d:\和/cygdrive / d /../../ == c:\ cygwin(或者你有的地方) Cygwin安装)。还要记住,反斜杠在Unix样式路径中用作转义字符,例如/ cygdrive / c / Documents \和\ Settings。 Cygpath做了一个令人惊讶的工作,照顾这些,如果它不可用它通常安全地假设你的奇怪的边缘情况不存在。
import sys
import subprocess
#Buncha code here ...
#We got somepath from somewhere, and don't know what format it's in.
try:
somepath = subprocess.check_output(['cygpath', '-m', somepath])
except subprocess.CalledProcessError:
#Cheap attempt at coping with the possibility that we're in Windows, but cygpath isn't available.
if sys.platform.startswith('win32'):
mypath = somepath.replace('\\', '/')
else:
mypath = somepath
#Now we can assume somepath is using forward slashes for delimiters.
如果您传递Windows样式路径,某些Windows命令会混淆,如果传入Windows或混合样式路径,某些Cygwin命令会混淆。例如,rsync可能会被“c:/foo/bar.txt”搞糊涂,因为看起来你正试图在名为“c”的远程计算机上指定“/foo/bar.txt”。当您调用其中一个挑剔的Windows或Cygwin程序时,请使用cygpath使其快乐。如果您正在调用一个挑剔的Windows程序并且没有cygpath,请尝试使用ghetto“winpath = mypath.replace('/','\')”方法。如果您正在转换Unix样式路径并且没有可用的Cygwin,我认为可能会失败,但希望如果您没有可用的Cygwin,那么在Windows上没有任何Unix样式路径可以开始... < / p>