2009-12-22 3 views
203

Приведенный ниже код не будет соединяться, когда отладка команды не сохраняет весь путь, а только последнюю запись.Почему в этом случае не работает os.path.join()?

os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/') 

Когда я проверить это он хранит только /new_sandbox/ часть кода.

ответ

272

Последние строки не должны начинаться с косой черты. Если они начинаются с косой черты, то они считаются «абсолютным путем», и все перед ними отбрасывается.

Цитируя Python docs for os.path.join:

Если компонент абсолютный путь, все предыдущие компоненты выбрасываются и соединение продолжается от абсолютного компонента пути.

Обратите внимание на Windows, поведение в отношении буквы дисков, которые, кажется, изменились по сравнению с предыдущими версиями Python:

В Windows, буква диска не сбрасывается, когда компонент абсолютного пути (например, r'\foo'). Если компонент содержит букву диска, все предыдущие компоненты выбрасываются, и буква диска сбрасывается. Обратите внимание, что поскольку существует текущий каталог для каждого диска, os.path.join("c:", "foo") представляет собой путь относительно текущего каталога на диске C: (c:foo), а не c:\foo.

+61

-1: ** Нет ** строка должна включать в себя символ «/». Одна цель os.path.join состоит в том, чтобы не помещать какие-либо слэши в путь. –

+0

это не круто. если я явно попрошу присоединиться к этим путям (или строкам), сделайте это, если есть ведущий «/» или нет в этом пути/строке. – aschmid00

+0

, если вы этого хотите, просто используйте str.join(), это os.path, и поэтому он согласуется с семантикой пакета. – marcorossi

12

не использовать прямую косую черту в начале компонентов пути, кроме случаев, когда ссылаюсь в корневой директории:

os.path.join('/home/build/test/sandboxes', todaystr, 'new_sandbox') 

Смотрите также: http://docs.python.org/library/os.path.html#os.path.join

4

Попробуйте с new_sandbox только

os.path.join('/home/build/test/sandboxes/', todaystr, 'new_sandbox') 
11

Это потому, что ваш '/new_sandbox/' начинается с / и, следовательно, предполагается, что он относится к корневому каталогу. Снять ведущий /.

3

сделать это так, не слишком дополнительные слэши

root="/home" 
os.path.join(root,"build","test","sandboxes",todaystr,"new_sandbox") 
122

Идея os.path.join(), чтобы сделать вашу программу кросс-платформенные (Linux/Windows/и т.д.).

Даже одна косая русалка.

Таким образом, это имеет смысл только при использовании с каким-то ориентиром, например os.environ['HOME'] или os.path.dirname(__file__).

53

os.path.join() может использоваться совместно с os.path.sep для создания абсолютного, а не относительного пути.

os.path.join(os.path.sep, 'home','build','test','sandboxes',todaystr,'new_sandbox') 
+4

Использование 'os.path.sep' как первого элемента для построения абсолютного пути лучше, чем любой другой ответ здесь! Весь смысл использования методов 'os.path', а не базовых str, заключается в том, чтобы не писать'/'. Также отлично подходит для каждого подкаталога в качестве нового аргумента и удаления всех косых черт. Вероятно, было бы неплохо убедиться в проверке, что 'todaystr' не начинается с косой черты! ;) – snooze92

+2

Это работает и на окнах (python 2.7.6). Он не интегрировался с «C: \» и присоединился к подкаталогам. – rickfoosusa

8

Чтобы понять, почему это удивительное поведение не полностью ужасны, рассмотрим приложение, которое принимает имя конфигурационного файла в качестве аргумента:

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 или подобного).

Это может быть не очень хорошо, но я считаю, что это мотивация для поведения абсолютного пути.

+0

Спасибо! Я всегда ненавидел это поведение, пока не прочел ваш ответ! Он задокументирован в https://docs.python.org/3.5/library/os.path.html#os.path.join, но не в его мотивации. –

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') 
0

Обратите внимание, что подобная проблема может укусить вас, если вы используете 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