WindowsのPython os.path.join


99

私はpythonを学習しようとしていますし、スクリプトを出力するプログラムを作成しています。os.path.joinを使用したいのですが、かなり混乱しています。私が言うならドキュメントによると:

os.path.join('c:', 'sourcedir')

わかります"C:sourcedir"。ドキュメントによると、これは正常ですよね?

しかし、私がcopytreeコマンドを使用すると、Pythonはそれを希望する方法で出力します。次に例を示します。

import shutil
src = os.path.join('c:', 'src')
dst = os.path.join('c:', 'dst')
shutil.copytree(src, dst)

ここに私が得るエラーコードがあります:

WindowsError:[エラー3]指定されたパスが見つかりません: 'C:src /*.*'

でラップするos.path.joinos.path.normpath、同じエラーが発生します。

これos.path.joinがこの方法で使用できない場合、私はその目的について混乱しています。

Stack Overflowによって提案されたページによると、スラッシュは結合で使用すべきではありません。それは正しいと思いますか?

回答:


59

Windowsには、各ドライブの現在のディレクトリという概念があります。そのため"c:sourcedir"、現在のC:ディレクトリ内の "sourcedir"を意味し、絶対ディレクトリを指定する必要があります。

これらのいずれも機能し、同じ結果が得られるはずですが、現時点で再確認するためにWindows VMを起動していません。

"c:/sourcedir"
os.path.join("/", "c:", "sourcedir")
os.path.join("c:/", "sourcedir")

8
os.path.join( 'C:/'、 'sourcedir')は期待どおりに機能しました。よろしくお願いします:)他の '//' 'c:' 'c:\\'は機能しませんでした(C:\\は2つのバックスラッシュを作成し、C:\はまったく機能しませんでした)ありがとうghostdog74 、Smashery、Roger Pate。私はあなたの借金をしている:)
フランクE.

申し訳ありませんが、改行はコメントに残されていませんでした

これがいくつかのケースで機能する場合でも、@ AndreasTによる答えははるかに優れたソリューションです。os.sepを使用すると、OSに応じて/または\が選択されます。
SenhorLucas

使用中の任意の点があるos.path.joinか、os.sepあなたが指定するつもりならc:、とにかくは?c:他のOSでは意味がありません。
naught101 2019

これらのソリューションはすべて、部分的にしか満足のいくものではありません。特定のケースが1つある場合は、手動でセパレーターを追加してもかまいませんが、プログラムで実行したい場合は、どのようにos.path.join('c:','folder')動作するのos.path.join('folder','file')でしょうか。それが原因なの:か、それとも「c:」がドライブなのか?
Vincenzooo

121

さらに知識を深めるために、最もpython docの一貫した答えは次のようになります。

mypath = os.path.join('c:', os.sep, 'sourcedir')

posixルートパスにもos.sepが必要なので、

mypath = os.path.join(os.sep, 'usr', 'lib')

5
私の無知を失礼します-コードはまだWindowsとLinuxで異なるので、何がos.sep優れているのですか?
pianoJames

3
注入しようとするときは、このスナフに注意してくださいos.sep。それは、裸のドライブ文字の後にのみ機能します。>>> os.path.join( "C:\さようなら"、os.sep、 "TEMP") 'C:\\ TEMP'
Jobu

1
@pianoJames私の答えはこれに基づいて構築され、システムにとらわれないソリューションを提供します:stackoverflow.com/a/51276165/3996580
Scott Gigante 2018

私は、これらすべての「知識のある」ソリューションの要点を理解していません。os.sepセパレーターを想定せずにパスを操作する場合に便利です。os.path.join()正しいセパレータをすでに知っているので、それを使っても意味がありません。最終的に、ルートディレクトリを名前で明示的に指定する必要がある場合も意味がありません(独自の例でわかるように)。なぜ"c:" + os.sep単に代わりに"c:\\"、またはos.sep + "usr"単に代わりに"/usr"?また、Winシェルではできないことに注意してください。ルート名は実際にはであるcd c:ことcd c:\ を示唆していますc:\
Michael Ekoka

13

理由os.path.join('C:', 'src')が期待どおりに機能しないのは、リンクしたドキュメントに何かがあるためです。

Windowsでは、各ドライブに現在のディレクトリがあるため、os.path.join( "c:"、 "foo")は、ドライブC:(c:foo)ではなく、cの現在のディレクトリに対する相対パスを表します。 :\ foo。

ゴーストドッグが言ったように、あなたはおそらく mypath=os.path.join('c:\\', 'sourcedir')


12

WindowsとLinuxの両方で機能するシステムに依存しないソリューションの場合、入力パスに関係なく、 os.path.join(os.sep, rootdir + os.sep, targetdir)

Windowsの場合:

>>> os.path.join(os.sep, "C:" + os.sep, "Windows")
'C:\\Windows'

Linuxの場合:

>>> os.path.join(os.sep, "usr" + os.sep, "lib")
'/usr/lib'

1
ありがとう!これは、@ Jobuが前述した落とし穴の影響を受けないため、さらに便利です。os.path.join(os.sep、 "C:\\ a" + os.sep、 "b")は "C: Windowsでは\\ a \\ b "。
pianoJames

1
これらの例のどちらもシステムにとらわれないのですか?c:* nixの上に存在しない、とusr...窓上に存在しない
naught101

関数呼び出しos.path.join(os.sep, rootdir + os.sep, targetdir)は、コードを変更する必要なく、これらのシステム固有の例の両方で機能するため、システムに依存しません。
Scott Gigante

この解決策は、それを触発した以前の投稿と同様に、のようにrootdirを設定することに依拠していますrootdir = "usr" if nix else "c:"。しかし、より直接的で正確なrootdir = "/usr" if nix else "c:\\"作品も同様に、os.sepアクロバットやそれに続く頭を引っかくことはありません。* nixのルートディレクトリがスラッシュ以外で始まる、またはWindowsの後にルートコロンとバックスラッシュなしで名前が付けられたルートディレクトリが存在する危険はありません(たとえば、Winシェルではcd c:、単に行うことはできません。末尾のバックスラッシュを指定する必要があります)、それでなぜそれ以外のふりをするのですか?
Michael Ekoka

11

わかりやすくするために、パスの区切り文字として/または\をハードコードすることはおそらくお勧めできません。たぶんこれが一番でしょうか?

mypath = os.path.join('c:%s' % os.sep, 'sourcedir')

または

mypath = os.path.join('c:' + os.sep, 'sourcedir')

7

これは(windows)pythonのバグだと思います。

なぜバグ?

このステートメントは True

os.path.join(*os.path.dirname(os.path.abspath(__file__)).split(os.path.sep))==os.path.dirname(os.path.abspath(__file__))

しかし、それはFalseWindowsマシン上です。


1
私はそれがPythonのバグを構成することに同意する傾向があります。これはまだ事実ですか?(2015後半の輝かしいユートピアの未来から書かれました。
セシルカレー

私はWindowsマシンにアクセスできないため、Windowsに関してこの質問に答えることはできませんが、この質問に関するpythonの動作は変更されていないと思います。とにかく、このステートメントはLinuxの実装にも当てはまりません。最初のステートメントは先頭の区切り文字なしでパス(別名ルートディレクトリ)を返し、2番目のステートメントは先頭の区切り文字を含むパスを返すためです。
georg

だから私はこの質問についての私の答えはもう好きではありません。しかし、これに関するpythonの動作も好きではありません。
georg

@Cecil同じ問題のため、私は今この質問にいます...それはまだ事実のようです。
joshmcode 2016年

5

Windowsパスに参加するには、

mypath=os.path.join('c:\\', 'sourcedir')

基本的に、スラッシュをエスケープする必要があります


4

Windowsでパスを処理するには、いくつかの可能なアプローチがあり、ハードコーディングされたもの(生の文字列リテラルを使用したり、バックスラッシュをエスケープしたりするもの)から最小限のものまであります。期待どおりに機能するいくつかの例を次に示します。ニーズに合ったものを使用してください。

In[1]: from os.path import join, isdir

In[2]: from os import sep

In[3]: isdir(join("c:", "\\", "Users"))
Out[3]: True

In[4]: isdir(join("c:", "/", "Users"))
Out[4]: True

In[5]: isdir(join("c:", sep, "Users"))
Out[5]: True

0

@ georg-への同意

なぜ私たちはラメが必要なのかを言いますos.path.join-使用する方が良いstr.joinか、unicode.join例えば

sys.path.append('{0}'.join(os.path.dirname(__file__).split(os.path.sep)[0:-1]).format(os.path.sep))

2
ええ、そうです、その方がずっとはっきりしています。なぜ正規表現を使用していないのですか?またはperlスクリプトを呼び出して出力を処理しますか?
ジーン・フランソワ・ファーブル

os.path.joinはかなり良いセマンティクスであるため、私はそれが良い考えだとは思いません...コードでそれを見て、何が起こっているのかをすぐに理解してください。
SenhorLucas

0

あなたのコメントに答える: 「他の '//' 'c:'、 'c:\\'は機能しませんでした(C:\\は2つのバックスラッシュを作成し、C:\はまったく機能しませんでした)」

Windowsでは、を使用 os.path.join('c:', 'sourcedir') すると\\sourcedirの前に2つのバックスラッシュが自動的に追加されます。

PythonはスラッシュでもWindows上で動作するように、パスを解決するには、 - > 「/」、単純に追加.replace('\\','/')してos.path.join以下のように: -

os.path.join('c:\\', 'sourcedir').replace('\\','/')

例えば: os.path.join('c:\\', 'temp').replace('\\','/')

出力:'C:/ temp'


0

提案されたソリューションは興味深いものであり、優れたリファレンスを提供しますが、それらは部分的にのみ満足しています。特定のケースが1つある場合、または入力文字列の形式がわかっている場合は、手動でセパレータを追加してもかまいませんが、一般的な入力に対してプログラムでそれを行いたい場合があります。

少し実験してみると、最初のセグメントがドライブ文字の場合、パス区切り文字は追加されない、つまり、実際の単位に対応しているかどうかに関係なく、コロンの後に続く単一の文字が追加されないことが基準になると思います。

例えば:

import os
testval = ['c:','c:\\','d:','j:','jr:','data:']

for t in testval:
    print ('test value: ',t,', join to "folder"',os.path.join(t,'folder'))
test value:  c: , join to "folder" c:folder
test value:  c:\ , join to "folder" c:\folder
test value:  d: , join to "folder" d:folder
test value:  j: , join to "folder" j:folder
test value:  jr: , join to "folder" jr:\folder
test value:  data: , join to "folder" data:\folder

基準をテストしてパス修正を適用する便利な方法os.path.splitdriveは、最初に返された要素をテスト値と比較することt+os.path.sep if os.path.splitdrive(t)[0]==t else tです。

テスト:

for t in testval:
    corrected = t+os.path.sep if os.path.splitdrive(t)[0]==t else t
    print ('original: %s\tcorrected: %s'%(t,corrected),' join corrected->',os.path.join(corrected,'folder'))
original: c:    corrected: c:\  join corrected-> c:\folder
original: c:\   corrected: c:\  join corrected-> c:\folder
original: d:    corrected: d:\  join corrected-> d:\folder
original: j:    corrected: j:\  join corrected-> j:\folder
original: jr:   corrected: jr:  join corrected-> jr:\folder
original: data: corrected: data:  join corrected-> data:\folder

おそらく末尾のスペースに対してより堅牢になるように改善することができ、私はそれをウィンドウでのみテストしましたが、それがアイデアを与えることを願っています。Os.pathも参照してください:この動作を説明できますか?ウィンドウ以外のシステムの興味深い詳細については。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.