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

chr*_*ley 307 python path

下面的代码将不会加入,在调试时,命令不会存储整个路径,只会存储最后一个条目.

os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/')
Run Code Online (Sandbox Code Playgroud)

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

Cra*_*een 400

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

引用Python文档os.path.join:

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

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

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

  • -1:**否**字符串应包含"/".os.path.join的一个重点是防止在路径中添加任何斜杠. (83认同)
  • 这是令人沮丧的,因为它是**隐含的魔法**,与[主要启发式](https://www.python.org/dev/peps/pep-0020)的"显式优于隐式"相反.它_is_.语言设计师可能认为他们知道的更好,但偶尔想要这样做存在明显且明显的安全理由.现在我们做不到.这就是为什么我们不能拥有好东西. (19认同)
  • @DustinRasener您可以使用[``os.path.normpath``](http://docs.python.org/2/library/os.path.html#os.path.normpath)来实现这一目标. (15认同)
  • str.join()的问题当然是它不会消除双斜杠.我认为这是使用os.path.join的人们的主要目的.例如'/'.join(['/etc/','/ conf'])导致三个斜杠:'/ etc /// conf' (6认同)
  • 不知道为什么人们对os.path.join行为感到沮丧.在其他语言中,等效的路径连接库/方法的行为完全相同.它更安全,更有意义. (5认同)
  • 这不酷。如果我明确要求加入那些路径(或字符串),则在该路径/字符串上是否存在前导“ /”时执行此操作。 (2认同)
  • 如果你想要的话,只需使用 str.join() ,这是 os.path ,因此它与其包语义一致。 (2认同)
  • @mmcrae:其他语言是真的吗?golang 绝对_not_ true:https://golang.org/pkg/path/#Join 展开示例并单击“运行”。我也不明白如何将 python 的方式视为更安全......带前导斜杠的用户输入可能导致引用关键系统文件。如果未对前导斜杠进行特殊处理,那么(最坏的情况)路径会引用不存在的文件/目录的深层路径。当然,用户输入应该被清理……但是这个功能不应该加剧问题! (2认同)
  • 什么是有效的(最好是常见的)场景,其中人们希望“os.path.join”中的后一个参数覆盖前一个路径部分(因为前导斜杠有效地删除了所有先前的参数)。 (2认同)
  • @chris你已经得到了你的“pwd”,某人(用户)给了你一个文件的路径,这很可能是pwd的相对路径,或者绝对路径。您想要的是 os.path.join( pwd, path) 忽略 pwd(如果路径是相对路径),否则附加它。这可能是开发者想到的场景 (2认同)

Ant*_*ins 147

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

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

所以被一些有点像一个参考点使用时它才有意义 os.environ['HOME']os.path.dirname(__file__).


小智 71

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

os.path.join(os.path.sep, 'home','build','test','sandboxes',todaystr,'new_sandbox')
Run Code Online (Sandbox Code Playgroud)

  • 使用`os.path.sep`作为构建绝对​​路径的第一个元素比这里的任何其他答案更好!使用`os.path`而不是基本的str方法的全部意义是避免编写`/`.将每个子目录作为新参数并删除所有斜杠也很棒.确保检查'todaystr`不是以斜线开头可能是个好主意!;) (7认同)
  • 这也适用于Windows(python 2.7.6).它没有与'C:\'相关并加入了子目录. (2认同)
  • @snooze92 唯一的问题是它更冗长且可读性更差。 (2认同)

mik*_*iku 22

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

os.path.join('/home/build/test/sandboxes', todaystr, 'new_sandbox')
Run Code Online (Sandbox Code Playgroud)

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


Dav*_*ver 19

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

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

如果应用程序执行时:

$ myapp foo.conf
Run Code Online (Sandbox Code Playgroud)

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

但请考虑如果调用应用程序时会发生什么:

$ myapp /some/path/bar.conf
Run Code Online (Sandbox Code Playgroud)

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

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

  • 必须不同意,这太可怕了。在这种情况下,您不应该使用简单的“sys.argv”输入来确定是否在前面添加“config_root”。所有“os.path.join”应该关心的是连接文件路径元素。 (3认同)
  • 谢谢!在阅读您的回答之前,我一直讨厌这种行为!它记录在 https://docs.python.org/3.5/library/os.path.html#os.path.join 中,但没有记录它的动机。 (2认同)
  • 此时此刻,您需要的正是许多人认为糟糕的解决方案。 (2认同)
  • 问题是这个名字选得不好。`os.path.join(p1, p2)` 所做的并不是真正连接 `p1` 和 `p2`,而是相对于 `p1` 使用 `p2`(或者如果 `p2` 是绝对路径则绝对连接) (2认同)

Amb*_*ber 12

这是因为你'/new_sandbox/'从a开始,/因此被认为是相对于根目录.删除前导/.


Nuc*_*eon 8

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

os.path.join(os.sep, 'home', 'build', 'test', 'sandboxes', todaystr, 'new_sandbox')
Run Code Online (Sandbox Code Playgroud)

要么

os.path.join(os.environ.get("HOME"), 'test', 'sandboxes', todaystr, 'new_sandbox')
Run Code Online (Sandbox Code Playgroud)


ope*_*onk 6

尝试的组合split("/"),并*与现有的连接字符串.

import os

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

os.path.join(*home.split("/"), todaystr, *new.split("/"))
Run Code Online (Sandbox Code Playgroud)


这个怎么运作...

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

* 在列表的前面突出列表的每个项目自己的参数

  • 这会将其变成相对路径而不是绝对路径 (2认同)

YOU*_*YOU 5

尝试new_sandbox仅使用

os.path.join('/home/build/test/sandboxes/', todaystr, 'new_sandbox')
Run Code Online (Sandbox Code Playgroud)