Windows 上的 Python os.path.join

发布于 2024-08-24 12:34:40 字数 715 浏览 9 评论 0原文

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

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: [Error 3] The system cannot find the path specified: 'C:src/*.*'

如果我用 os.path 包装 os.path.join .normpath 我得到同样的错误。

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

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

I am trying to learn python and am making a program that will output a script. I want to use os.path.join, but am pretty confused. According to the docs if I say:

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

I get "C:sourcedir". According to the docs, this is normal, right?

But when I use the copytree command, Python will output it the desired way, for example:

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

Here is the error code I get:

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.

If this os.path.join can't be used this way, then I am confused as to its purpose.

According to the pages suggested by Stack Overflow, slashes should not be used in join—that is correct, I assume?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

糖粟与秋泊 2024-08-31 12:34:40

更迂腐的是,最与 python 文档一致的答案是:

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

因为你还需要 os.sep 作为 posix 根路径:

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

To be even more pedantic, the most python doc consistent answer would be:

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

Since you also need os.sep for the posix root path:

mypath = os.path.join(os.sep, 'usr', 'lib')
北陌 2024-08-31 12:34:40

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

其中任何一个都应该可以工作并给出相同的结果,但我目前没有启动 Windows 虚拟机来仔细检查:

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

Windows has a concept of current directory for each drive. Because of that, "c:sourcedir" means "sourcedir" inside the current C: directory, and you'll need to specify an absolute directory.

Any of these should work and give the same result, but I don't have a Windows VM fired up at the moment to double check:

"c:/sourcedir"
os.path.join("/", "c:", "sourcedir")
os.path.join("c:/", "sourcedir")
橘味果▽酱 2024-08-31 12:34:40

迂腐地说,将 / 或 \ 硬编码为路径分隔符可能不好。也许这会是最好的?

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

或者

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

To be pedantic, it's probably not good to hardcode either / or \ as the path separator. Maybe this would be best?

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

or

mypath = os.path.join('c:' + os.sep, 'sourcedir')
兮颜 2024-08-31 12:34:40

对于可在 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")
'C:\\Windows'
>>> joinpath("C:\\Windows", "src")
'C:\\Windows\\src'

在 Linux 上:

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

For a system-agnostic solution that works on both Windows and Linux, no matter what the input path, one could use

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

On Windows:

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

On Linux:

>>> joinpath("usr", "lib")
'/usr/lib'
>>> joinpath("/usr", "lib")
'/usr/lib'
>>> joinpath("/usr/lib", "src")
'/usr/lib/src'
涫野音 2024-08-31 12:34:40

os.path.join('C:', 'src') 未按您预期工作的原因是您链接到的文档中的某些内容:

请注意,在 Windows 上,因为有
每个驱动器的当前目录,
os.path.join("c:", "foo") 代表一个
相对于当前目录的路径
在驱动器 C: (c:foo) 上,而不是 c:\foo。

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

The reason os.path.join('C:', 'src') is not working as you expect is because of something in the documentation that you linked to:

Note that on Windows, since there is a
current directory for each drive,
os.path.join("c:", "foo") represents a
path relative to the current directory
on drive C: (c:foo), not c:\foo.

As ghostdog said, you probably want mypath=os.path.join('c:\\', 'sourcedir')

久而酒知 2024-08-31 12:34:40

我想说这是一个(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__))

但在Windows机器上它是False

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

Why bug?

I think this statement should be True

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

But it is False on windows machines.

美羊羊 2024-08-31 12:34:40

要加入 Windows 路径,

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

基本上尝试一下,您需要转义斜杠

to join a windows path, try

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

basically, you will need to escape the slash

撞了怀 2024-08-31 12:34:40

您有几种可能的方法来处理 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

You have a few possible approaches to treat path on Windows, from the most hardcoded ones (as using raw string literals or escaping backslashes) to the least ones. Here follows a few examples that will work as expected. Use what better fits your needs.

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
请帮我爱他 2024-08-31 12:34:40

同意@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))

Consent with @georg-

I would say then why we need lame os.path.join- better to use str.join or unicode.join e.g.

sys.path.append('{0}'.join(os.path.dirname(__file__).split(os.path.sep)[0:-1]).format(os.path.sep))
多情出卖 2024-08-31 12:34:40

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

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

要解析路径,因为 python 在 Windows 上也可以使用正斜杠 -> '/',只需将 .replace('\\','/') 添加到 os.path 即可。加入如下:-

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

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

输出:'C:/temp'

answering to your comment : "the others '//' 'c:', 'c:\\' did not work (C:\\ created two backslashes, C:\ didn't work at all)"

On windows using
os.path.join('c:', 'sourcedir')
will automatically add two backslashes \\ in front of sourcedir.

To resolve the path, as python works on windows also with forward slashes -> '/', simply add .replace('\\','/') with os.path.join as below:-

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

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

output : 'C:/temp'

鹤舞 2024-08-31 12:34:40

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

经过一些实验,我认为标准是,如果第一段是驱动器号,则不添加路径分隔符,这意味着单个字母后跟冒号,无论它是否对应于实际单位。

例如:

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'))
测试值:c:,加入“文件夹”c:folder
测试值: c:\ ,加入到“文件夹” c:\folder
测试值: d: ,加入到“文件夹” d:folder
测试值: j: ,加入到“文件夹” j:folder
测试值: jr: ,加入“文件夹” jr:\folder
测试值: data: ,加入到“文件夹” 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'))
原文:c: 更正:c:\ join 更正-> c:\文件夹
原文:c:\ 更正:c:\ 加入更正-> c:\文件夹
原文:d: 更正:d:\ 加入更正-> d:\文件夹
原文:j: 更正:j:\ 加入更正-> j:\文件夹
原文:jr:更正:jr:加入更正-> jr:\文件夹
原始:数据:更正:数据:加入更正->数据:\文件夹

它可能可以改进为对于尾随空格更加健壮,我只在 Windows 上测试了它,但我希望它能提供一个想法。
另请参阅 Os.path :你能解释一下这种行为吗? 有趣的Windows 以外的系统的详细信息。

The proposed solutions are interesting and offer a good reference, however they are only partially satisfying. It is ok to manually add the separator when you have a single specific case or you know the format of the input string, but there can be cases where you want to do it programmatically on generic inputs.

With a bit of experimenting, I believe the criteria is that the path delimiter is not added if the first segment is a drive letter, meaning a single letter followed by a colon, no matter if it corresponds to a real unit.

For example:

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

A convenient way to test for the criteria and apply a path correction can be to use os.path.splitdrive comparing the first returned element to the test value, like t+os.path.sep if os.path.splitdrive(t)[0]==t else t.

Test:

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

it can be probably be improved to be more robust for trailing spaces, and I have tested it only on windows, but I hope it gives an idea.
See also Os.path : can you explain this behavior? for interesting details on systems other then windows.

潇烟暮雨 2024-08-31 12:34:40

我通过使用以下方法解决了这个问题:

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)

I got around this by using:

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

join here is not from os.path.join(), but from ''.join()

It can be useful in the following situation:

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)
倦话 2024-08-31 12:34:40

为了简单起见,解决方法:

my_path = r'D:\test\test2\file.txt' # original path string
drive_letter = my_path.split(':')[0] # avoid os.path.join relative path bs
my_path_parts = os.path.normpath(my_path.split(':')[1]).split(os.sep)

# do some path cmponent modifications here if you want

if drive_letter: # if drive letter exists
    drive_letter += ':\\'

my_new_path = drive_letter + os.path.join(*my_path_parts)
my_new_path

For simplicity's sake, a workaround:

my_path = r'D:\test\test2\file.txt' # original path string
drive_letter = my_path.split(':')[0] # avoid os.path.join relative path bs
my_path_parts = os.path.normpath(my_path.split(':')[1]).split(os.sep)

# do some path cmponent modifications here if you want

if drive_letter: # if drive letter exists
    drive_letter += ':\\'

my_new_path = drive_letter + os.path.join(*my_path_parts)
my_new_path
相权↑美人 2024-08-31 12:34:40

在 Windows 中使用 os.paht.join("/", "Temp") 默认情况下会导致 /Temp,但听起来很奇怪,使用该路径作为完整路径没有问题相当于“C:/Temp”,它适用于保存文件和打开文件。

In windows using os.paht.join("/", "Temp") will result in /Temp by default but as strange as it sounds, there is no problem in using that path as a full path equivalent to "C:/Temp" and it works for both saving files and opening files.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文