Почему в этом случае не работает 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