Почему в этом случае не работает os.path.join()?
Приведенный ниже код не будет объединяться, когда отладка команды не сохраняет весь путь, а только последнюю запись.
os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/')
Когда я тестирую это, он сохраняет только часть /new_sandbox/
кода.
Ответы
Ответ 1
Последние строки не должны начинаться с косой черты. Если они начинаются с косой черты, то они считаются "абсолютным путем", и все до них отбрасывается.
Цитирование Документы Python для os.path.join
:
Если компонент является абсолютным путем, все предыдущие компоненты выбрасываются, и соединение продолжается от компонента абсолютного пути.
Примечание о Windows, поведение по отношению к буквам диска, которое, похоже, изменилось по сравнению с более ранними версиями Python:
В Windows буква диска не является reset, когда встречается компонент абсолютного пути (например, r'\foo'
). Если компонент содержит букву диска, все предыдущие компоненты выбрасываются, а буква диска reset. Обратите внимание, что поскольку для каждого диска существует текущий каталог, os.path.join("c:", "foo")
представляет путь относительно текущего каталога на диске C:
(c:foo
), а не c:\foo
.
Ответ 2
Идея os.path.join()
заключается в том, чтобы сделать вашу программу кросс-платформенной (linux/windows/etc).
Даже одна черта рушится.
Таким образом, это имеет смысл только при использовании с некоторой точкой отсчета, например
os.environ['HOME']
или os.path.dirname(__file__)
.
Ответ 3
os.path.join()
может использоваться совместно с os.path.sep
для создания абсолютного, а не относительного пути.
os.path.join(os.path.sep, 'home','build','test','sandboxes',todaystr,'new_sandbox')
Ответ 4
Не используйте прямую косую черту в начале компонентов пути, кроме случаев обращения к корневому каталогу:
os.path.join('/home/build/test/sandboxes', todaystr, 'new_sandbox')
см. также: http://docs.python.org/library/os.path.html#os.path.join
Ответ 5
Чтобы понять, почему это удивительное поведение не совсем ужасно, рассмотрите приложение, которое принимает имя файла конфигурации в качестве аргумента:
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
или аналогичный).
Это может быть не очень хорошо, но я считаю, что это мотивация для поведения абсолютного пути.
Ответ 6
Это потому, что ваш '/new_sandbox/'
начинается с /
и поэтому считается относительным к корневому каталогу. Удалите ведущий /
.
Ответ 7
Чтобы сделать вашу функцию более переносимой, используйте ее как таковую:
os.path.join(os.sep, 'home', 'build', 'test', 'sandboxes', todaystr, 'new_sandbox')
или
os.path.join(os.environ.get("HOME"), 'test', 'sandboxes', todaystr, 'new_sandbox')
Ответ 8
Попробуйте комбинировать 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', '']
*
перед списком выделяет каждый элемент списка своим собственным параметром
Ответ 9
Попробуйте только new_sandbox
os.path.join('/home/build/test/sandboxes/', todaystr, 'new_sandbox')
Ответ 10
сделайте это так, без лишних слэшей
root="/home"
os.path.join(root,"build","test","sandboxes",todaystr,"new_sandbox")
Ответ 11
Обратите внимание, что подобная проблема может вас укусить, если вы используете 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
Ответ 12
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