Windows上的Python os.path.join


98

我正在尝试学习python,正在制作一个将输出脚本的程序。我想使用os.path.join,但是很困惑。根据文档,如果我说:

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

我懂了"C:sourcedir"。根据文档,这是正常的,对吗?

但是当我使用copytree命令时,Python将以所需的方式输出它,例如:

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

这是我得到的错误代码:

WindowsError:[错误3]系统找不到指定的路径:'C:src /*.*'

如果我用换行os.path.joinos.path.normpath则会得到相同的错误。

如果os.path.join不能以这种方式使用它,那么我对其目的感到困惑。

根据Stack Overflow建议的页面,在连接中不应该使用斜杠-是的,我认为是正确的吗?

Answers:


59

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

这些中的任何一个都应该工作并给出相同的结果,但是目前我还没有启动Windows VM进行仔细检查:

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

8
os.path.join('C:/','sourcedir')正常工作。我非常感谢您,先生:)其他'//''c:''c:\\'不起作用(C:\\创建了两个反斜杠,C:\根本不起作用)再次感谢ghostdog74 ,Smashery和Roger Pate。我对您负有责任:)
Frank E.

抱歉,没有对换行符发表评论,它看起来非常混乱
Frank E.

即使这在某些情况下可行,@ AndreasT的答案也是更好的解决方案。使用os.sep将根据操作系统在/和\之间进行选择。
SenhorLucas

使用时有什么意义吗,os.path.join或者无论如何os.sep都要指定c:c:在其他操作系统上没有任何意义。
naught101 '19

所有这些解决方案仅部分令人满意。如果您有一个特定的案例,可以手动添加分隔符,但是如果您要通过编程方式进行分隔,则与分隔符os.path.join('c:','folder')不同的标准是什么os.path.join('folder','file')?是因为:还是因为'c:`是驱动器?
Vincenzooo

121

要进一步讲究知识,最符合python doc的答案是:

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

由于您还需要os.sep作为posix根路径:

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

4
不好意思-看起来Windows和Linux之间的代码仍然不同,那么什么才是os.sep上乘的呢?
詹姆斯·詹姆斯(James)

3
尝试注射时,请注意此提示os.sep。它仅在裸盘驱动器号之后起作用。>>> os.path.join(“ C:\ goodbye”,os.sep,“ temp”)'C:\\
temp'– Jobu

1
@pianoJames我的答案是基于此提供的,以提供与系统无关的解决方案:stackoverflow.com/a/51276165/3996580
Scott Gigante,

我不理解所有这些“学究的”解决方案的意义。os.sep当您想要在不对分隔符进行假设的情况下操纵路径时,此功能很有用。与它一起使用毫无意义,os.path.join()因为它已经知道正确的分隔符。如果最终需要通过名称显式指定根目录(这在您自己的示例中可以看到),这也没有意义。为什么"c:" + os.sep而不是简单地"c:\\",或os.sep + "usr"而不是简单地"/usr"?还要注意在Win shell中你不能cd c:但可以cd c:\ ,提示根名称实际上是c:\
Michael Ekoka

13

之所以os.path.join('C:', 'src')无法正常工作,是因为您链接到了文档中的某些内容:

请注意,在Windows上,由于每个驱动器都有一个当前目录,所以os.path.join(“ c:”,“ foo”)表示相对于驱动器C:(c:foo)上当前目录的路径,而不是c :\ foo

正如ghostdog所说,您可能想要 mypath=os.path.join('c:\\', 'sourcedir')


12

对于在Windows和Linux上均可使用的与系统无关的解决方案,无论输入路径如何,都可以使用 os.path.join(os.sep, rootdir + os.sep, targetdir)

在窗口上:

>>> os.path.join(os.sep, "C:" + os.sep, "Windows")
'C:\\Windows'

在Linux上:

>>> os.path.join(os.sep, "usr" + os.sep, "lib")
'/usr/lib'

1
谢谢!这一点更加有用,因为它不会受到@Jobu前面提到的陷阱的困扰:os.path.join(os.sep,“ C:\\ a” + os.sep,“ b”)返回“ C: Windows上的\\ a \\ b“​​。
pianoJames

1
这些示例中的任何一个如何与系统无关?c:在* nix usr上不存在,在Windows上也不存在
。.– naught101

该函数调用os.path.join(os.sep, rootdir + os.sep, targetdir)完全与系统无关,因为它可以与这两个系统特定的示例一起使用,而无需更改代码。
Scott Gigante

此解决方案与早期启发它的帖子非常相似,仍然依赖于将rootdir设置为rootdir = "usr" if nix else "c:"。但是,更直接,更准确的rootdir = "/usr" if nix else "c:\\"工作也一样,没有os.sep杂技和随后的抓挠。* nix上的根目录不会以正斜杠开头,也不会存在Windows的根目录名称不带冒号和反斜杠的情况(例如,在Win shell中,您不能只是这样做cd c:,需要指定结尾的反斜杠),那么为什么要假装否则呢?
Michael Ekoka

11

要学究,将/或\硬编码为路径分隔符可能不好。也许这是最好的?

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

要么

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

7

我会说这是一个(windows)python错误。

为什么要臭虫?

我认为这句话应该是 True

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

但这是False在Windows机器上。


1
我倾向于同意这构成了Python错误。还是这样吗?(摘自2015年末辉煌的乌托邦式未来。
Cecil Curry

关于Windows,我无法回答此问题,因为我无法使用Windows机器,但是我认为python在此问题上的行为没有改变。无论如何,该语句对于Linux实现也是不正确的,因为第一条语句返回不带前导分隔符(又名根目录)的路径,而第二条语句返回包含前导分隔符的路径。
乔治2015年

因此,我实际上不再喜欢我对此问题的回答。但是我也不喜欢python的行为。
乔治2015年

@Cecil由于相同的问题,我现在在这个问题上……似乎仍然如此。
joshmcode

5

加入Windows路径,请尝试

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

基本上,您将需要逃脱斜线


4

您可以使用几种可能的方法来处理Windows上的路径,从最硬编码的方法(如使用原始字符串文字或转义反斜杠)到最少的方法。以下是一些可以按预期工作的示例。使用更适合您需求的产品。

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

0

同意@ georg-

我会说为什么我们需要la脚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))

2
是的,对,这样更清楚了。为什么不使用正则表达式呢?或调用perl脚本并处理输出?
让弗朗索瓦法布尔

我认为这不是一个好主意,因为os.path.join的语义非常好……所以您可以在代码中看到它并立即了解发生了什么。
SenhorLucas

0

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

在Windows上,using os.path.join('c:', 'sourcedir') 将自动\\sourcedir前面添加两个反斜杠。

解析路径,因为python在Windows上也可以使用正斜杠-> “/”,只需.replace('\\','/')os.path.join如下: -

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

例如: os.path.join('c:\\', 'temp').replace('\\','/')

输出: 'C:/ temp'


0

所提出的解决方案很有趣并且可以提供很好的参考,但是它们只是部分令人满意。当您遇到单个特定情况或知道输入字符串的格式时,可以手动添加分隔符,但是在某些情况下,您可能希望对通用输入进行编程编程。

经过一些试验,我相信标准是,如果第一个段是驱动器号(即单个字母后跟一个冒号),则不添加路径定界符,无论它是否对应于实际单位。

例如:

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

可能可以对其进行改进以使其更适合尾随空间,并且我仅在Windows上对其进行了测试,但我希望它能给出一个主意。另请参见Os.path:您可以解释这种行为吗?有关Windows以外的其他系统的有趣信息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.