以下のコードは結合されません。デバッグすると、コマンドはパス全体ではなく最後のエントリのみを保存します。
os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/')
これをテストすると/new_sandbox/
、コードの一部のみが保存されます。
以下のコードは結合されません。デバッグすると、コマンドはパス全体ではなく最後のエントリのみを保存します。
os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/')
これをテストすると/new_sandbox/
、コードの一部のみが保存されます。
回答:
後者の文字列はスラッシュで始めるべきではありません。スラッシュで始まる場合は、「絶対パス」と見なされ、それより前のすべてが破棄されます。
コンポーネントが絶対パスの場合、以前のすべてのコンポーネントは破棄され、結合は絶対パスコンポーネントから続行されます。
Windowsでは、ドライブ文字に関連する動作が、以前のバージョンのPythonと比較して変更されているようです。
Windowsでは、絶対パスコンポーネント(たとえば
r'\foo'
)が検出されても、ドライブ文字はリセットされません。コンポーネントにドライブ文字が含まれている場合、以前のすべてのコンポーネントは破棄され、ドライブ文字がリセットされます。各ドライブos.path.join("c:", "foo")
には現在のディレクトリがあるため、ではなく、ドライブC:
(c:foo
)の現在のディレクトリからの相対パスを表すことに注意してくださいc:\foo
。
os.path.normpath
その目的を達成するために使用できます。
のアイデア os.path.join()
、プログラムをクロスプラットフォーム(linux / windows / etc)にすることです。
たった1人のスラッシュでもそれを台無しにします。
したがって、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', '']
*
リストの前で、リストの各項目を独自のパラメーターで分割します
余分なスラッシュもなしに、このようにしてください
root="/home"
os.path.join(root,"build","test","sandboxes",todaystr,"new_sandbox")
を使用する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
2番目以降の文字列から文字列を取り除き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"
...意図した結果ではないかと思います。