Наведений нижче код не приєднається, коли налагоджена команда не зберігає весь шлях, а лише останній запис.
os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/')
Коли я тестую це, він зберігає лише /new_sandbox/
частину коду.
Наведений нижче код не приєднається, коли налагоджена команда не зберігає весь шлях, а лише останній запис.
os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/')
Коли я тестую це, він зберігає лише /new_sandbox/
частину коду.
Відповіді:
Останні рядки не повинні починатися з косої риски. Якщо вони починають з косою рискою, то вони вважаються "абсолютною стежкою", і все перед ними відкидається.
Цитуючи документи Python дляos.path.join
:
Якщо компонент є абсолютним шляхом, всі попередні компоненти викидаються і з'єднання триває з компонента абсолютного шляху.
Зауважте, що в Windows поведінка стосовно букв диска, яка, здається, змінилася порівняно з попередніми версіями Python:
У Windows букву диска не скидають, коли
r'\foo'
зустрічається абсолютний компонент шляху (наприклад, ). Якщо компонент містить літеру диска, всі попередні компоненти викидаються, а літера диска скидається. Зауважте, що оскільки існує поточний каталог для кожного диска,os.path.join("c:", "foo")
являє собою шлях відносно поточного каталогу на дискуC:
(c:foo
), а неc:\foo
.
os.path.normpath
для досягнення цієї мети.
Ідея os.path.join()
полягає в тому, щоб зробити вашу програму крос-платформою (linux / windows / тощо).
Навіть одна косою рискою її розорить.
Отже, це має сенс лише при використанні з якоюсь точкою відліку, як-от
os.environ['HOME']
або os.path.dirname(__file__)
.
os.path.join()
може використовуватися спільно з os.path.sep
для створення абсолютного, а не відносного шляху.
os.path.join(os.path.sep, 'home','build','test','sandboxes',todaystr,'new_sandbox')
os.path.sep
як першого елемента для побудови абсолютного шляху краще, ніж будь-яка інша відповідь тут! Весь сенс використання, os.path
а не основних методів str, полягає у тому, щоб уникнути написання /
. Розміщення кожного підкаталогу як нового аргументу та видалення всіх косої риски також чудово. Напевно, це було б хорошою ідеєю, щоб переконатися в тому, що чек todaystr
не починається з косої риски! ;)
Не використовуйте прямі косої риски на початку компонентів шляху, за винятком випадків переходу до кореневого каталогу:
os.path.join('/home/build/test/sandboxes', todaystr, 'new_sandbox')
дивіться також: http://docs.python.org/library/os.path.html#os.path.join
Щоб зрозуміти, чому це дивне поведінка не зовсім страшне, розгляньте програму, яка приймає ім'я файлу конфігурації як аргумент:
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.environ.get("HOME"), 'test', 'sandboxes', todaystr, 'new_sandbox')
Спробуйте комбінувати 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', '']
*
перед списком розбиває кожен елемент списку власний параметр
Зауважте, що аналогічна проблема може вас перекусити, якщо ви 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
Я рекомендую зняти рядок із другого та наступних рядків 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)
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("\\"))
, який дає результат "/b"
... Я сумніваюся, що це задуманий результат.