bestsource

Windows에서의 Python os.path.join

bestsource 2023. 4. 9. 21:46
반응형

Windows에서의 Python os.path.join

나는 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)

표시되는 에러 코드는 다음과 같습니다.

Windows Error : [ Error 3 ]시스템이 지정된 경로를 찾을 수 없습니다: 'C:src/*.*'

포장을 하면os.path.join와 함께os.path.normpath같은 에러가 발생.

이 경우os.path.join이런 식으로 사용할 수 없는 경우, 그 용도가 헷갈립니다.

Stack Overflow에서 제안하는 페이지에 따르면 조인 시 슬래시를 사용하면 안 됩니다. 맞습니까?

좀 더 현학적으로 말하면, 가장 일관된 대답은 다음과 같습니다.

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

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

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

Windows 에는, 각 드라이브에 대해서 현재의 디렉토리의 개념이 있습니다.그렇기 때문에"c:sourcedir"는, 현재의 C:디렉토리내의 「sourcedir」를 의미하기 때문에, 절대 디렉토리를 지정할 필요가 있습니다.

다음 중 어느 것이든 작동하여 동일한 결과를 얻을 수 있지만, 현재 Windows VM을 다시 확인할 수는 없습니다.

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

알기 쉽게 말하면 / 또는 \를 경로 구분자로 하드코드하는 것은 좋지 않을 수 있습니다.이게 최선일까요?

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

또는

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

Windows와 Linux 모두에서 작동하는 시스템에 구애받지 않는 솔루션이라면 어떤 입력 경로에서도 사용할 수 있습니다.

def joinpath(rootdir, targetdir):
    return os.path.join(os.sep, rootdir + os.sep, targetdir)

Windows 의 경우:

>>> joinpath("C:", "Windows")
'C:\\Windows'
>>> joinpath("C:\\Windows", "src")
'C:\\Windows\\src'

Linux의 경우:

>>> joinpath("usr", "lib")
'/usr/lib'
>>> joinpath("/usr/lib", "src")
'/usr/lib/src'

이유os.path.join('C:', 'src')가 예상대로 동작하지 않는 이유는 다음 링크에 접속한 매뉴얼에 기재되어 있는 어떤 것이 원인입니다.

Windows 에서는, 각 드라이브에 현재의 디렉토리가 있기 때문에, os.path.join("c:")은, c:\foo 가 아니고, C:(c:foo) 드라이브의 현재 디렉토리에 상대적인 패스를 나타냅니다.

고스트독이 말했듯이, 당신은 아마mypath=os.path.join('c:\\', 'sourcedir')

이것은 피톤 벌레라고 할 수 있습니다.

왜 버그일까요?

이 진술은 다음과 같아야 한다고 생각합니다.True

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

그러나 그것은 그렇다.FalseWindows 머신에 탑재되어 있습니다.

윈도 패스에 참여하려면

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

기본적으로, 당신은 슬레이시를 벗어나야 할 것이다.

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

@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))

"다른 '/' 'c:', 'c:\\'가 작동하지 않았습니다(C:\\\는 2개의 백슬래시를 생성했고, C:\는 전혀 작동하지 않았습니다).

Windows 에서는, 를 사용하면, sourceir 의 앞에 2 개의 백슬래시가 자동적으로 추가됩니다.

경로를 해결하려면 python이 Windows에서도 슬래시 -> /를 사용하여 동작하기 때문에 다음과 같이 추가합니다.

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

예:

출력 : 'C:/temp'

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

조금 실험해 본 결과, 첫 번째 세그먼트가 드라이브 문자(실제 유닛에 대응하는지 여부에 관계없이 단일 문자 뒤에 콜론)인 경우 경로 구분 기호가 추가되지 않는 것이 기준이라고 생각합니다.

예를 들어 다음과 같습니다.

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'도 참조해 주세요.동작에 대해 설명해 주시겠습니까?를 참조해 주세요.

저는 다음 방법으로 이 문제를 해결했습니다.

os.sep.join(list('C:', 'sourcedir'))

join여기서부터가 아니다os.path.join(), 단, 로부터''.join()

이 기능은 다음과 같은 경우에 도움이 됩니다.

import os

some_path = r'C:\some_folder\some_file.txt'
path_items = some_path.split(os.sep)
same_path = os.sep.join(path_items)

For simplicity's sake, a workaround:

my_path = r'D:\test\test2\file.txt' # original path string
drive_letter = my_path.split(':')[0] # avoid os.path.join relative path bs
my_path_parts = os.path.normpath(my_path.split(':')[1]).split(os.sep)

# do some path cmponent modifications here if you want

if drive_letter: # if drive letter exists
    drive_letter += ':\\'

my_new_path = drive_letter + os.path.join(*my_path_parts)
my_new_path

창에서는 다음을 사용합니다.os.paht.join("/", "Temp")디폴트로는 /Temp가 됩니다만, 이상하게 들릴지 모르지만, 그 패스를 「C:/Temp」에 상당하는 풀 패스로서 사용하는 것은 문제가 없고, 파일 보존과 파일 오픈의 양쪽 모두에 유효합니다.

ReferenceURL : https://stackoverflow.com/questions/2422798/python-os-path-join-on-windows

반응형