web-dev-qa-db-ja.com

この場合、os.path.join()が機能しないのはなぜですか?

以下のコードは、デバッグ時にパス全体を格納するのではなく、最後のエントリだけを格納するため、参加しません。

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

これをテストすると、コードの/new_sandbox/部分だけが格納されます。

281
chrissygormley

後者の文字列はスラッシュで始めるべきではありません。それらがスラッシュで始まっているなら、それらは「絶対パス」と考えられ、それらの前のすべては捨てられます。

Pythonドキュメントのos.path.join の引用

コンポーネントが絶対パスの場合、以前のすべてのコンポーネントは破棄され、結合は絶対パスコンポーネントから続行されます。

Windowsでは、ドライブ文字に関連した動作が以前のPythonバージョンと比べて変更されているように思われることに注意してください。

Windowsでは、絶対パスコンポーネント(例:r'\foo')が検出されてもドライブ文字はリセットされません。コンポーネントにドライブ文字が含まれていると、それ以前のすべてのコンポーネントは破棄され、ドライブ文字はリセットされます。各ドライブには現在のディレクトリがあるため、os.path.join("c:", "foo")C:ではなくドライブc:fooc:\foo)上の現在のディレクトリからの相対パスを表します。

377
Craig McQueen

os.path.join()のアイデアはあなたのプログラムをクロスプラットフォーム(linux/windows/etc)にすることです。

スラッシュが1つでもそれを台無しにします。

そのため、os.environ['HOME']os.path.dirname(__file__)のようなある種の参照ポイントと一緒に使用されている場合にのみ意味があります。

140

os.path.join()os.path.sepと組み合わせて使用​​すると、相対パスではなく絶対パスを作成できます。

os.path.join(os.path.sep, 'home','build','test','sandboxes',todaystr,'new_sandbox')
64
ghammond

ルートディレクトリを参照する場合を除き、パスコンポーネントの先頭にスラッシュを使用しないでください。

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

http://docs.python.org/library/os.path.html#os.path.join もご覧ください。

20
miku

この驚くべき振る舞いが完全にそれほどひどいものではない理由を理解するのを助けるために、引数として設定ファイル名を受け入れるアプリケーションを考えてください:

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のようなものではありません)。

それは素晴らしいことではないかもしれませんが、これが絶対パスの振る舞いの動機であると思います。

16
David Wolever

それはあなたの'/new_sandbox/'/で始まっているので、ルートディレクトリからの相対パスであると仮定されているからです。先頭の/を削除してください。

11
Amber

あなたの機能をよりポータブルにするために、それを次のように使用してください。

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
NuclearPeon

既存の結合を持つ文字列に対して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', '']

リストの前にある*は、リストの各項目をそれ自身のパラメータから取り出します。

6
openwonk

new_sandboxのみで試してください

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

余分なスラッシュもなく、このようにしてください。

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

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.jpg"という名前のファイルではなく "foobar"という名前のフォルダになってしまいます。これを防ぐには、拡張子を別に追加する必要があります。

return os.path.join("avatars", instance.username, prefix) + extension
0
shacker