Windows 上的 Python os.path.join

我正在尝试学习 python,并且正在编写一个可以输出脚本的程序。我想用 os.path. join 但是我很困惑。根据 医生,如果我说:

os.path.join('c:', 'sourcedir')

我得了 "C:sourcedir"根据医生的说法,这是正常的,对吧?

但是,当我使用 copitree 命令时,Python 将按照预期的方式输出它,例如:

import shutil
src = os.path.join('c:', 'src')
dst = os.path.join('c:', 'dst')
shutil.copytree(src, dst)

下面是我得到的错误代码:

WindowsError: [Error 3] The system cannot find the path specified: 'C:src/*.*'

If I wrap the os.path.join with os.path.normpath I get the same error.

如果这个 os.path.join不能这样使用,那么我对它的用途感到困惑。

根据 Stack Overflow 建议的页面,斜杠不应该在 join & mash; 中使用,对吗?

158048 次浏览

要加入 windows 路径,请尝试

mypath=os.path.join('c:\\', 'sourcedir')

基本上,你需要避开斜线

os.path.join('C:', 'src')之所以不能像您预期的那样工作,是因为您链接到的文档中的某些内容:

Note that on Windows, since there is a 每个硬盘的工作目录 Join (“ c:”,“ foo”)表示一个 相对于工作目录的路径 在驱动器 C 上: (c: foo) ,而不是 c: foo。

正如 Ghostdog 所说,你可能需要 mypath=os.path.join('c:\\', 'sourcedir')

Windows 对每个驱动器都有一个工作目录概念。因此,"c:sourcedir"意味着当前 C: 目录中的“ sourcedir”,您需要指定一个绝对目录。

所有这些应该工作,并给出相同的结果,但我没有一个 Windows 虚拟机启动的时候,仔细检查:

"c:/sourcedir"
os.path.join("/", "c:", "sourcedir")
os.path.join("c:/", "sourcedir")

为了显得迂腐,硬编码或者作为路径分隔符可能都不太好。也许这样最好?

mypath = os.path.join('c:%s' % os.sep, 'sourcedir')

或者

mypath = os.path.join('c:' + os.sep, 'sourcedir')

更迂腐的是,Python doc 中最一致的答案是:

mypath = os.path.join('c:', os.sep, 'sourcedir')

因为 posx 根路径也需要 os.sep:

mypath = os.path.join(os.sep, 'usr', 'lib')

I'd say this is a (windows)python bug.

为什么是虫子?

我认为这个声明应该是 True

os.path.join(*os.path.dirname(os.path.abspath(__file__)).split(os.path.sep))==os.path.dirname(os.path.abspath(__file__))

但它是 False的窗口机器。

同意@georg-

我会说为什么我们需要蹩脚的 os.path.join-更好地使用 str.joinunicode.join例如。

sys.path.append('{0}'.join(os.path.dirname(__file__).split(os.path.sep)[0:-1]).format(os.path.sep))

在 Windows 上有几种可能的方法来处理 path,从最硬编码的方法(如使用原始字符串文字或转义反斜杠)到最少的方法。下面是一些按预期工作的示例。使用最适合你需要的东西。

In[1]: from os.path import join, isdir


In[2]: from os import sep


In[3]: isdir(join("c:", "\\", "Users"))
Out[3]: True


In[4]: isdir(join("c:", "/", "Users"))
Out[4]: True


In[5]: isdir(join("c:", sep, "Users"))
Out[5]: True

对于同时适用于 Windows 和 Linux 的系统无关解决方案,无论输入路径是什么,都可以使用

def joinpath(rootdir, targetdir):
return os.path.join(os.sep, rootdir + os.sep, targetdir)

在 Windows 上:

>>> joinpath("C:", "Windows")
'C:\\Windows'
>>> joinpath("C:\\Windows", "src")
'C:\\Windows\\src'

在 Linux 上:

>>> joinpath("usr", "lib")
'/usr/lib'
>>> joinpath("/usr/lib", "src")
'/usr/lib/src'

回应你的评论: “其他”//“ c:”,“ c:”不起作用(C: 创建了两个反斜杠,C: 根本不起作用)

窗口使用 os.path.join('c:', 'sourcedir') 将自动添加两个反斜杠 \\前面的 < strong > source dir

为了解决这个问题,当 python 在 windows 上也使用正斜杠-> '/'时,只需添加 .replace('\\','/')os.path.join,如下所示:-

os.path.join('c:\\', 'sourcedir').replace('\\','/')

e.g: os.path.join('c:\\', 'temp').replace('\\','/')

输出: “ C:/temp”

提出的解决方案是有趣的,并提供了很好的参考,但他们只是部分满意。当您有一个特定的用例或者您知道输入字符串的格式时,手动添加分隔符是可以的,但是在某些情况下,您可能希望通过编程方式在一般输入上添加分隔符。

经过一些实验,我相信标准是,如果第一段是一个驱动器字母,就不添加路径分隔符,这意味着一个字母后面跟一个冒号,不管它是否对应一个真正的单位。

例如:

import os
testval = ['c:','c:\\','d:','j:','jr:','data:']


for t in testval:
print ('test value: ',t,', join to "folder"',os.path.join(t,'folder'))
test value:  c: , join to "folder" c:folder
test value:  c:\ , join to "folder" c:\folder
test value:  d: , join to "folder" d:folder
test value:  j: , join to "folder" j:folder
test value:  jr: , join to "folder" jr:\folder
test value:  data: , join to "folder" data:\folder

测试条件和应用路径校正的一种方便方法是使用 os.path.splitdrive将第一个返回的元素与测试值进行比较,如 t+os.path.sep if os.path.splitdrive(t)[0]==t else t

测试:

for t in testval:
corrected = t+os.path.sep if os.path.splitdrive(t)[0]==t else t
print ('original: %s\tcorrected: %s'%(t,corrected),' join corrected->',os.path.join(corrected,'folder'))
original: c:    corrected: c:\  join corrected-> c:\folder
original: c:\   corrected: c:\  join corrected-> c:\folder
original: d:    corrected: d:\  join corrected-> d:\folder
original: j:    corrected: j:\  join corrected-> j:\folder
original: jr:   corrected: jr:  join corrected-> jr:\folder
original: data: corrected: data:  join corrected-> data:\folder

我们可以改进它,使它在后面的空间更加健壮,我只在窗户上测试过,但我希望它能给出一个想法。 有关除窗口以外的系统的有趣细节,请参见 你能解释这种行为吗?

I got around this by using:

os.sep.join(list('C:', 'sourcedir'))

这里的 join不是来自 os.path.join(),而是来自 ''.join()

它在下列情况下可能是有用的:

import os


some_path = r'C:\some_folder\some_file.txt'
path_items = some_path.split(os.sep)
same_path = os.sep.join(path_items)