Python 为什么';t os.path.join()在这种情况下有效吗?
下面的代码将不会加入,调试时,该命令不会存储整个路径,而只存储最后一个条目Python 为什么';t os.path.join()在这种情况下有效吗?,python,path,Python,Path,下面的代码将不会加入,调试时,该命令不会存储整个路径,而只存储最后一个条目 os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/') 当我测试这个时,它只存储代码的/new\u sandbox/部分。后面的字符串不应该以斜杠开头。如果它们以斜线开头,那么它们被视为“绝对路径”,前面的所有内容都被丢弃 引述: 如果组件是绝对路径,则会丢弃所有以前的组件,并从绝对路径组件继续连接 注意:在Windows上,与驱动器
os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/')
当我测试这个时,它只存储代码的
/new\u sandbox/
部分。后面的字符串不应该以斜杠开头。如果它们以斜线开头,那么它们被视为“绝对路径”,前面的所有内容都被丢弃
引述:
如果组件是绝对路径,则会丢弃所有以前的组件,并从绝对路径组件继续连接
注意:在Windows上,与驱动器号相关的行为与早期Python版本相比似乎有所改变:
在Windows上,遇到绝对路径组件(例如,r'\foo'
)时,不会重置驱动器号。如果某个组件包含驱动器号,则会丢弃以前的所有组件并重置驱动器号。请注意,由于每个驱动器都有一个当前目录,os.path.join(“c:,“foo”)
表示相对于驱动器c:
(c:foo
)上当前目录的路径,而不是c:\foo
不要在路径组件的开头使用正斜杠,除非引用根目录:
os.path.join('/home/build/test/sandboxes', todaystr, 'new_sandbox')
另请参见:仅尝试使用
新沙盒
os.path.join('/home/build/test/sandboxes/', todaystr, 'new_sandbox')
这是因为您的
'/new_sandbox/'
以/
开头,因此假定它是相对于根目录的。删除前导的/
这样做,不要太多额外的斜杠
root="/home"
os.path.join(root,"build","test","sandboxes",todaystr,"new_sandbox")
os.path.join()
哪怕是一刀都会毁了它
因此,它只有在与某种参考点一起使用时才有意义,例如
os.environ['HOME']
或os.path.dirname(\uu文件\uu)
os.path.join()
可与os.path.sep
结合使用,以创建绝对路径而非相对路径
os.path.join(os.path.sep, 'home','build','test','sandboxes',todaystr,'new_sandbox')
帮助理解这个奇怪的行为为什么不是完全可怕的,考虑一个应用程序,它接受一个配置文件名作为一个参数:
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
或类似文件)
它可能不太好,但我相信这就是绝对路径行为的动机。要使您的功能更具可移植性,请将其作为一种方式使用:
os.path.join(os.sep, 'home', 'build', 'test', 'sandboxes', todaystr, 'new_sandbox')
或
请注意,如果您使用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)
即使扩展名
可能是.jpg
,最终也会得到一个名为“foobar”的文件夹,而不是一个名为“foobar.jpg”的文件。要防止出现这种情况,需要单独附加扩展名:
return os.path.join("avatars", instance.username, prefix) + extension
对于具有现有联接的字符串,请尝试组合使用拆分(“/”
和*
。
import os
home = '/home/build/test/sandboxes/'
todaystr = '042118'
new = '/new_sandbox/'
os.path.join(*home.split("/"), todaystr, *new.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','sandboxs','']
列表前面的*
将列表中的每一项分解为它自己的参数
os.path.join("a", *"/b".split(os.sep))
'a/b'
更完整的版本:
import os
def join (p, f, sep = os.sep):
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, sep = os.sep):
print("os.path.join({}, {}) => {}".format(p, f, os.path.join(p, f)))
print(" join({}, {}) => {}".format(p, f, join(p, f, sep)))
if __name__ == "__main__":
# /a/b/c for all
test("\\a\\b", "\\c", "\\") # optionally pass in the sep you are using locally
test("/a/b", "/c", "/")
test("/a/b", "c")
test("/a/b/", "c")
test("", "/c")
test("", "c")
您可以剥离“/”
:
>>> os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/'.strip('/'))
'/home/build/test/sandboxes/04122019/new_sandbox'
我建议从第二个字符串和以下字符串中删除字符串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)
-1:任何字符串都不应包含“/”。os.path.join的一个要点是防止在路径中添加任何斜杠。当然,str.join()的问题在于它不会消除双斜杠。我认为这是使用os.path.join的人们的主要目的。e、 g.“/”.join(['/etc/','/conf'])会导致三个斜杠:“/etc///conf'@DustinRasener您可以用来实现这个目标。不知道人们为什么对os.path.join行为感到沮丧。在其他语言中,等效路径联接库/方法的行为完全相同。它更安全,更有意义。这是令人沮丧的,因为这是一种隐性魔法,与“显性优于隐性”的说法相反。事实确实如此。语言设计者可能认为他们知道得更好,但偶尔想这样做显然有安全的理由。现在我们不能。这就是为什么我们不能有好东西。使用os.path.sep
作为构建绝对路径的第一个元素比这里的任何其他答案都好!使用os.path
而不是基本str方法的全部目的是避免编写/
。将每个子目录作为新参数并删除所有斜杠也很好。最好通过检查确保todaystr
不以斜杠开头!;)这也适用于windows(python 2.7.6)。它没有引用“C:\”并加入子目录。谢谢!在读到你的答案之前,我一直讨厌这种行为!这是在中记录的,但不是它的动机。此时此刻,当你需要许多人认为糟糕的解决方案时。不得不不同意,这是完全糟糕的。在这种情况下,您不应该使用幼稚的sys.argv
输入来确定是否在config_root
前加前缀。所有os.path.join
都应该关注的是连接文件路径元素。问题是名称选择不当。os.path.join(p1,p2)
所做的并不是真正地连接p1
和p2
,而是采取p2
相对于p1
(或者如果p2
是绝对路径)的方式,如果os.sep实际上是“\”
?然后您的第一个示例变成os.path.join