Windows의 Python os.path.join


98

나는 파이썬을 배우려고 노력하고 있으며 스크립트를 출력하는 프로그램을 만들고 있습니다. 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 : [Error 3] 지정한 경로를 찾을 수 없습니다 : 'C : src /*.*'

os.path.join와 함께 포장하면 os.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 : \\는 두 개의 백 슬래시를 만들었고 C : \는 전혀 작동하지 않았습니다) 다시 한 번 감사합니다 ghostdog74 , Smashery 및 Roger Pate. 나는 :) 당신의 빚이다
프랭크 E.

죄송합니다, 줄 바꿈이 코멘트에 보관되지 않은, 그것은 매우 지저분한 외모
프랭크 E.

이것이 어떤 경우에 작동하더라도 @AndreasT의 대답이 훨씬 더 나은 솔루션입니다. os.sep를 사용하면 OS에 따라 /와 \ 중에서 선택됩니다.
SenhorLucas

사용 하는 것이 중요 os.path.join하거나 어쨌든 os.sep지정하려는 경우가 c:있습니까? c:다른 OS에서는 의미가 없습니다.
naught101

이 모든 솔루션은 부분적으로 만 만족합니다. 특정 사례가 하나 인 경우 구분 기호를 수동으로 추가하는 것이 좋지만 프로그래밍 방식으로 수행하려는 경우 os.path.join('c:','folder')와 다르게 작동 하는 기준은 무엇 os.path.join('folder','file')입니까? 이 때문에의인가 :또는 때문에 'C :'드라이브는?
Vincenzooo

121

더 현명하게 말하면 가장 파이썬 문서 일관된 대답은 다음과 같습니다.

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

posix 루트 경로에 os.sep도 필요하기 때문에 :

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

4
실례합니다. Windows와 Linux간에 코드가 여전히 다른 것 같습니다. 그렇다면 무엇이 더 os.sep우수할까요?
pianoJames

3
주사를 시도 할 때이 snafu에주의하십시오 os.sep. 베어 드라이브 문자 후에 만 ​​작동합니다. >>> os.path.join ( "C : \ 작별 인사", os.sep, "온도") 'C : \\ TEMP'
Jobu

1
: 내 대답은 시스템에 얽매이지 솔루션을 제공하기 위해이 하나 떨어져 빌드 @pianoJames stackoverflow.com/a/51276165/3996580
스콧 GIGANTE

나는이 모든 "페단 틱"솔루션의 요점을 이해하지 못합니다. 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 : (c : foo) 드라이브의 현재 디렉토리에 상대적인 경로를 나타냅니다. : \ foo.

ghostdog가 말했듯이, 당신은 아마도 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 jul.

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 승 쉘의 예 뒤에 콜론과 백 슬래시 (없이라는 이름의 루트 디렉토리에있을 것이라는 점을, 당신은 그냥 할 수 없어 없습니다 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
나는 그것이 파이썬 버그를 구성한다는 것에 동의하는 경향이 있습니다. 이것이 여전히 사실입니까? ( 늦게 2015 년의 영광스러운 유토피아 적 미래에서 서면 )
세실 카레

Windows 시스템에 대한 액세스 권한이 없기 때문에 Windows와 관련 하여이 질문에 답할 수는 없지만이 질문에 대한 Python의 동작은 변경되지 않은 것 같습니다. 어쨌든, 첫 번째 명령문은 선행 구분 기호 (루트 디렉토리라고도 함)없이 경로를 리턴하는 반면 두 번째 명령문은 선행 구분 기호를 포함하는 경로를 리턴하기 때문에이 명령문은 Linux 구현에서도 해당되지 않습니다.
georg

그래서 저는이 질문에 대한 제 대답이 더 이상 마음에 들지 않습니다. 그러나 나는 또한 이것에 관한 파이썬의 행동을 좋아하지 않습니다.
georg

@Cecil 나는 같은 문제 때문에 지금이 질문에 있습니다 ... 아직도 마찬가지입니다.
joshmcode

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 스크립트를 호출하고 출력을 처리합니까?
Jean-François Fabre

나는 그것이 좋은 생각이라고 생각하지 않는다. 왜냐하면 os.path.join은 꽤 좋은 의미이기 때문이다. 그래서 당신은 그것을 코드에서보고 무슨 일이 일어나고 있는지 바로 이해한다.
SenhorLucas

0

귀하의 의견에 대한 답변 : "다른 '//' 'c :', 'c : \\'는 작동하지 않았습니다 (C : \\는 두 개의 백 슬래시를 만들었으며 C : \는 전혀 작동하지 않았습니다)"

Windows에서를 사용 os.path.join('c:', 'sourcedir') 하면 sourcedir\\ 앞에 두 개의 백 슬래시가 자동으로 추가됩니다. .

파이썬은 슬래시로도 윈도우에서 작동하기 때문에, 경로를 해결하려면 -> '를 /' 단순히 추가 .replace('\\','/')os.path.join아래와 같이 : -

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

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

출력 : 'C : / temp'


0

제안 된 솔루션은 흥미롭고 좋은 참조를 제공하지만 부분적으로 만 만족합니다. 단일 특정 케이스가 있거나 입력 문자열의 형식을 알고있는 경우 구분 기호를 수동으로 추가하는 것이 좋지만 일반 입력에 대해 프로그래밍 방식으로 수행하려는 경우가있을 수 있습니다.

약간의 실험을 통해 기준은 첫 번째 세그먼트가 드라이브 문자 인 경우 경로 구분 기호가 추가되지 않는다는 것입니다. 즉, 실제 단위에 해당하더라도 콜론이 뒤에 오는 단일 문자를 의미합니다.

예를 들면 :

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.