os.path.join - 我可以在Windows和Cygwin之间获得一致性吗?

时间:2011-05-12 11:08:35

标签: python windows cygwin filenames

我非常喜欢一组文件名组件,它们会在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'

2 个答案:

答案 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>