개발/Python

[파이썬] os.path.join()이 작동하지 않는 이유?

MinorMan 2023. 1. 22. 03:14
반응형

<질문>

아래 코드는 조인하지 않습니다. 디버그할 때 명령은 전체 경로를 저장하지 않고 마지막 항목만 저장합니다.

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

이것을 테스트하면/new_sandbox/코드의 일부입니다.


<답변1>

후자의 문자열은 슬래시로 시작하면 안 됩니다. 슬래시로 시작하면 "절대 경로"로 간주되며 그 앞의 모든 항목은 삭제됩니다.

인용Python docs for os.path.join:

구성 요소가 절대 경로인 경우 이전 구성 요소는 모두 버리고 절대 경로 구성 요소에서 결합이 계속됩니다.

Windows에서 이전 Python 버전과 비교하여 변경된 것으로 보이는 드라이브 문자와 관련된 동작을 참고하십시오.

Windows에서 절대 경로 구성 요소(예: r'\foo')를 만나면 드라이브 문자가 재설정되지 않습니다. 구성 요소에 드라이브 문자가 포함되어 있으면 이전의 모든 구성 요소가 폐기되고 드라이브 문자가 재설정됩니다. 각 드라이브에 대한 현재 디렉터리가 있으므로 os.path.join("c:", "foo")는 c:\foo가 아니라 드라이브 C:(c:foo)의 현재 디렉터리에 상대적인 경로를 나타냅니다. .


<답변2>

의 아이디어os.path.join()프로그램을 크로스 플랫폼(linux/windows/etc)으로 만드는 것입니다.

한 번의 슬래시라도 망칩니다.

따라서 다음과 같은 일종의 기준점과 함께 사용될 때만 의미가 있습니다.os.environ['HOME']또는os.path.dirname(__file__).


<답변3>

os.path.join()와 함께 사용할 수 있습니다.os.path.sep상대 경로가 아닌 절대 경로를 생성합니다.

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

<답변4>

루트 디렉토리를 참조할 때를 제외하고 경로 구성 요소의 시작 부분에 슬래시를 사용하지 마십시오.

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

또한보십시오:http://docs.python.org/library/os.path.html#os.path.join


<답변5>

이 놀라운 행동이 왜 그렇지 않은지 이해를 돕기 위해전적으로끔찍합니다. 구성 파일 이름을 인수로 받아들이는 응용 프로그램을 고려하십시오.

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또는 유사).

대단하지 않을 수도 있지만 이것이 절대 경로 동작의 동기라고 생각합니다.


<답변6>

그것은 당신의'/new_sandbox/'로 시작/따라서 루트 디렉토리에 상대적인 것으로 간주됩니다. 선행 제거/.


<답변7>

기존 조인이 있는 문자열에 대해 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', '']

*목록 앞에서 목록의 각 항목 자체 매개 변수를 나눕니다.


<답변8>

함수를 더 이식성 있게 만들려면 다음과 같이 사용하십시오.

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

또는

os.path.join(os.environ.get("HOME"), 'test', 'sandboxes', todaystr, 'new_sandbox')

<답변9>

함께 시도new_sandbox

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

<답변10>

추가 슬래시없이 이렇게하십시오

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

<답변11>

다음을 사용하면 유사한 문제가 발생할 수 있습니다.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

<답변12>

당신은 할 수 있습니다strip그만큼'/':

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

<답변13>

두 번째 및 다음 문자열에서 문자열을 제거하는 것이 좋습니다.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)

<답변14>

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

<답변15>

문제는 노트북이 Window를 실행 중일 수 있다는 것입니다. 그리고 Window는 슬래시 '/' 대신 백래시를 귀찮게 사용합니다.
프로그램을 크로스 플랫폼(linux/windows/etc)으로 만들기 위해. os.path.join 에서 슬래시를 제대로 처리하려면 경로에 슬래시(정방향 또는 역방향)를 제공하면 안 됩니다. 다음을 사용해야 합니다.

os.path.join(os.environ.get("HOME"), 'test', 'sandboxes', todaystr, 'new_sandbox')

아니면 좀 던져Path(__file__).resolve().parent(현재 파일의 상위 경로) 또는 내부에 슬래시를 사용하지 않도록 하는 모든 항목os.path.join


<답변16>

이해를 위해 다음 코드 스니펫을 참조하십시오.os.path.join(a, b)

a = '/home/user.name/foo/'
b = '/bar/file_name.extension'

print(os.path.join(a, b))
>>> /bar/file_name.extension

또는

a = '/home/user.name/foo'
b = '/bar/file_name.extension'
print(os.path.join(a, b))
>>> /bar/file_name.extension

하지만 때

a = '/home/user.name/foo/'
b = 'bar/file_name.extension'

print(os.path.join(a, b))
>>> /bar/file_name.extension

또는

a = '/home/user.name/foo'
b = 'bar/file_name.extension'
print(os.path.join(a, b))
>>> /home/user.name/foo/bar/file_name.extension
반응형