问题:为什么os.path.join()在这种情况下不起作用?
下面的代码将不会加入,调试后,该命令将不会存储整个路径,而只会存储最后一个条目。
os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/')
当我对此进行测试时,它仅存储/new_sandbox/
部分代码。
The below code will not join, when debugged the command does not store the whole path but just the last entry.
os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/')
When I test this it only stores the /new_sandbox/
part of the code.
回答 0
后面的字符串不应以斜杠开头。如果它们以斜杠开头,那么它们将被视为“绝对路径”,并且丢弃它们之前的所有内容。
将Python文档os.path.join
引用为:
如果组件是绝对路径,则所有先前的组件都将被丢弃,并且连接将从绝对路径组件继续。
请注意,在Windows上,与驱动器号有关的行为与早期的Python版本相比似乎有所变化:
在Windows上,r'\foo'
遇到绝对路径组件(例如)时,不会重置驱动器号。如果某个组件包含驱动器号,则会丢弃所有先前的组件,并重置驱动器号。请注意,由于每个驱动器都有一个当前目录,因此os.path.join("c:", "foo")
表示相对于驱动器C:
(c:foo
)上当前目录的路径,而不是c:\foo
。
The latter strings shouldn’t start with a slash. If they start with a slash, then they’re considered an “absolute path” and everything before them is discarded.
Quoting the Python docs for os.path.join
:
If a component is an absolute path, all previous components are thrown away and joining continues from the absolute path component.
Note on Windows, the behaviour in relation to drive letters, which seems to have changed compared to earlier Python versions:
On Windows, the drive letter is not reset when an absolute path component (e.g., r'\foo'
) is encountered. If a component contains a drive letter, all previous components are thrown away and the drive letter is reset. Note that 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
.
回答 1
的想法os.path.join()
是使您的程序跨平台(linux / windows / etc)。
即使是一个斜杠也会破坏它。
因此,仅当与某种参考点(例如os.environ['HOME']
或)一起使用时,它才有意义
os.path.dirname(__file__)
。
The idea of os.path.join()
is to make your program cross-platform (linux/windows/etc).
Even one slash ruins it.
So it only makes sense when being used with some kind of a reference point like
os.environ['HOME']
or os.path.dirname(__file__)
.
回答 2
os.path.join()
可以与一起使用,os.path.sep
以创建绝对路径而不是相对路径。
os.path.join(os.path.sep, 'home','build','test','sandboxes',todaystr,'new_sandbox')
os.path.join()
can be used in conjunction with os.path.sep
to create an absolute rather than relative path.
os.path.join(os.path.sep, 'home','build','test','sandboxes',todaystr,'new_sandbox')
回答 3
回答 4
为了帮助理解为什么这种令人惊讶的行为并不完全可怕,请考虑接受配置文件名作为参数的应用程序:
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
类似文件)。
可能不是很好,但是我相信这是绝对路径行为的动机。
To help understand why this surprising behavior isn’t entirely terrible, consider an application which accepts a config file name as an argument:
config_root = "/etc/myapp.conf/"
file_name = os.path.join(config_root, sys.argv[1])
If the application is executed with:
$ myapp foo.conf
The config file /etc/myapp.conf/foo.conf
will be used.
But consider what happens if the application is called with:
$ myapp /some/path/bar.conf
Then myapp
should use the config file at /some/path/bar.conf
(and not /etc/myapp.conf/some/path/bar.conf
or similar).
It may not be great, but I believe this is the motivation for the absolute path behaviour.
回答 5
这是因为您'/new_sandbox/'
以a开头,/
因此被假定为相对于根目录。拆下龙头/
。
It’s because your '/new_sandbox/'
begins with a /
and thus is assumed to be relative to the root directory. Remove the leading /
.
回答 6
为了使您的功能更具可移植性,请按以下方式使用它:
os.path.join(os.sep, 'home', 'build', 'test', 'sandboxes', todaystr, 'new_sandbox')
要么
os.path.join(os.environ.get("HOME"), 'test', 'sandboxes', todaystr, 'new_sandbox')
To make your function more portable, use it as such:
os.path.join(os.sep, 'home', 'build', 'test', 'sandboxes', todaystr, 'new_sandbox')
or
os.path.join(os.environ.get("HOME"), 'test', 'sandboxes', todaystr, 'new_sandbox')
回答 7
尝试使用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', '']
*
列表前面的内容将列表中的每个项目分解成自己的参数
Try combo of split("/")
and *
for strings with existing joins.
import os
home = '/home/build/test/sandboxes/'
todaystr = '042118'
new = '/new_sandbox/'
os.path.join(*home.split("/"), todaystr, *new.split("/"))
How it works…
split("/")
turns existing path into list: ['', 'home', 'build', 'test', 'sandboxes', '']
*
in front of the list breaks out each item of list its own parameter
回答 8
new_sandbox
仅尝试
os.path.join('/home/build/test/sandboxes/', todaystr, 'new_sandbox')
Try with new_sandbox
only
os.path.join('/home/build/test/sandboxes/', todaystr, 'new_sandbox')
回答 9
这样做,没有太多的斜线
root="/home"
os.path.join(root,"build","test","sandboxes",todaystr,"new_sandbox")
do it like this, without too the extra slashes
root="/home"
os.path.join(root,"build","test","sandboxes",todaystr,"new_sandbox")
回答 10
请注意,如果您使用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
Note that a similar issue can bite you if you use os.path.join()
to include an extension that already includes a dot, which is what happens automatically when you use os.path.splitext()
. In this example:
components = os.path.splitext(filename)
prefix = components[0]
extension = components[1]
return os.path.join("avatars", instance.username, prefix, extension)
Even though extension
might be .jpg
you end up with a folder named “foobar” rather than a file called “foobar.jpg”. To prevent this you need to append the extension separately:
return os.path.join("avatars", instance.username, prefix) + extension
回答 11
你可以strip
在'/'
:
>>> os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/'.strip('/'))
'/home/build/test/sandboxes/04122019/new_sandbox'
you can strip
the '/'
:
>>> os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/'.strip('/'))
'/home/build/test/sandboxes/04122019/new_sandbox'
回答 12
我建议从第二个和后面的字符串中删除字符串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)
I’d recommend to strip from the second and the following strings the string os.path.sep
, preventing them to be interpreted as absolute paths:
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)
回答 13
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("a", *"/b".split(os.sep))
'a/b'
a fuller version:
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")