为什么os.path.join()在这种情况下不起作用?

时间:2009-12-22 11:53:29

标签: python path

以下代码不会加入,调试时命令不存储整个路径,只存储最后一个条目。

os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/')

当我测试它时,它只存储代码的/new_sandbox/部分。

14 个答案:

答案 0 :(得分:375)

后面的字符串不应以斜杠开头。如果他们以斜线开头,则它们被视为“绝对路径”,并且它们之前的所有内容都将被丢弃。

引用Python docs for os.path.join

  

如果组件是绝对路径,则抛弃所有先前的组件,并从绝对路径组件继续连接。

关于Windows的注意事项,与驱动器号有关的行为,与早期的Python版本相比似乎有所改变:

  

在Windows上,遇到绝对路径组件(例如r'\foo')时,不会重置驱动器号。如果组件包含驱动器号,则会丢弃所有先前的组件并重置驱动器号。请注意,由于每个驱动器都有一个当前目录,os.path.join("c:", "foo")表示相对于驱动器C:c:foo)上当前目录的路径,而不是c:\foo

答案 1 :(得分:139)

os.path.join()的想法是让你的程序跨平台(linux / windows / etc)。

即使是一个斜线也会破坏它。

所以只有在使用某种参考点时才有意义 os.environ['HOME']os.path.dirname(__file__)

答案 2 :(得分:64)

os.path.join()可与os.path.sep结合使用,以创建绝对路径而不是相对路径。

os.path.join(os.path.sep, 'home','build','test','sandboxes',todaystr,'new_sandbox')

答案 3 :(得分:20)

不要在路径组件的开头使用正斜杠,除非在引用根目录时使用:

os.path.join('/home/build/test/sandboxes', todaystr, 'new_sandbox')

另见:http://docs.python.org/library/os.path.html#os.path.join

答案 4 :(得分:15)

为了帮助理解为什么这个令人惊讶的行为不是完全可怕的,请考虑一个接受配置文件名作为参数的应用程序:

config_root = "/etc/myapp.conf/"
file_name = os.path.join(config_root, sys.argv[1])

如果应用程序执行:

$ myapp foo.conf

将使用配置文件/etc/myapp.conf/foo.conf

但请考虑如果使用以下方式调用应用程序会发生什么:

$ myapp /some/path/bar.conf

然后myapp 使用/some/path/bar.conf(而不是/etc/myapp.conf/some/path/bar.conf或类似的)配置文件。

这可能不是很好,但我相信这是绝对路径行为的动机。

答案 5 :(得分:11)

这是因为您的'/new_sandbox/'/开头,因此被假定为相对于根目录。删除前导/

答案 6 :(得分:8)

为了使您的功能更具便携性,请使用它:

os.path.join(os.sep, 'home', 'build', 'test', 'sandboxes', todaystr, 'new_sandbox')

os.path.join(os.environ.get("HOME"), 'test', 'sandboxes', todaystr, 'new_sandbox')

答案 7 :(得分:6)

尝试使用split("/")*对具有现有联接的字符串进行组合。

import os

home = '/home/build/test/sandboxes/'
todaystr = '042118'
new = '/new_sandbox/'

os.path.join(*home.split("/"), todaystr, *new.split("/"))


工作原理......

split("/")将现有路径转换为列表:['', 'home', 'build', 'test', 'sandboxes', '']

列表前面的

*将每个列表项分解为自己的参数

答案 8 :(得分:3)

仅使用new_sandbox

os.path.join('/home/build/test/sandboxes/', todaystr, 'new_sandbox')

答案 9 :(得分:2)

这样做,没有额外的斜线

root="/home"
os.path.join(root,"build","test","sandboxes",todaystr,"new_sandbox")

答案 10 :(得分:0)

请注意,如果您使用os.path.join()包含已包含点的扩展程序,则类似的问题可能会让您感到困惑,这是您使用os.path.splitext()时自动执行的操作。在这个例子中:

components = os.path.splitext(filename)
prefix = components[0]
extension = components[1]
return os.path.join("avatars", instance.username, prefix, extension)

即使extension可能是.jpg,您最终也会找到一个名为" foobar"的文件夹。而不是一个名为" foobar.jpg"的文件。为防止这种情况,您需要单独附加扩展名:

return os.path.join("avatars", instance.username, prefix) + extension

答案 11 :(得分:0)

os.path.join("a", *"/b".split(os.sep))
'a/b'

完整版本:

import os

def join (p, f):
    f = os.path.normpath(f)
    if p == "":
        return (f);
    else:
        p = os.path.normpath(p)
        return (os.path.join(p, *f.split(os.sep)))

def test (p, f):
    print("os.path.join({}, {}) => {}".format(p, f, os.path.join(p, f)))
    print("        join({}, {}) => {}".format(p, f, join(p, f)))

if __name__ == "__main__":
    # /a/b/c for all
    test("/a/b", "/c")
    test("/a/b", "c")
    test("/a/b/", "c")
    test("", "/c")
    test("", "c")

收益:

os.path.join(/a/b, /c) => /c
        join(/a/b, /c) => /a/b/c
os.path.join(/a/b, c) => /a/b/c
        join(/a/b, c) => /a/b/c
os.path.join(/a/b/, c) => /a/b/c
        join(/a/b/, c) => /a/b/c
os.path.join(, /c) => /c
        join(, /c) => /c
os.path.join(, c) => c
        join(, c) => c

答案 12 :(得分:0)

您可以strip '/'

>>> os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/'.strip('/'))
'/home/build/test/sandboxes/04122019/new_sandbox'

答案 13 :(得分:0)

我建议从第二个及以下字符串中删除字符串os.path.sep,以防止将它们解释为绝对路径:

first_path_str = '/home/build/test/sandboxes/'
original_other_path_to_append_ls = [todaystr, '/new_sandbox/']
other_path_to_append_ls = [
    i_path.strip(os.path.sep) for i_path in original_other_path_to_append_ls
]
output_path = os.path.join(first_path_str, *other_path_to_append_ls)