source

Python의 상대 경로

lovecheck 2022. 12. 18. 08:40
반응형

Python의 상대 경로

코드베이스에 있는 템플릿 파일 몇 개를 현재 디렉토리에 복사하는 작업을 위한 간단한 도우미 스크립트를 만들고 있습니다.그러나 템플릿이 저장되어 있는 디렉토리에 대한 절대 경로가 없습니다.스크립트의 상대 경로가 있지만 스크립트를 호출하면 현재 작업 디렉토리에 대한 상대 경로로 간주됩니다.대신 이 상대 URL을 스크립트 위치에서 가져오도록 지정할 수 있는 방법이 있습니까?

스크립트가 있는 파일에서는 다음과 같은 작업을 수행합니다.

import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

그러면 원하는 파일에 대한 절대 경로가 제공됩니다.setuptools를 사용하는 경우 패키지 리소스 API를 사용해야 합니다.

업데이트: 코드 샘플을 붙여넣기 위해 코멘트에 응답합니다. :- )

라고 생각하는 것이 맞습니까?__file__항상 사용할 수 있는 것은 아닙니다(예를 들어 파일을 Import하지 않고 직접 실행하는 경우).

은 그...을 __main__스크립트는 파일을 직접 실행하는 것을 언급할 때 사용합니다.것 X 의 2.5).python 2.5.1).

#foo.py
import os
print os.getcwd()
print __file__

#in the interactive interpreter
>>> import foo
/Users/jason
foo.py

#and finally, at the shell:
~ % python foo.py
/Users/jason
foo.py

하지만, 저는 이 사건에 대한 몇가지 기묘한 점이 있다는 것을 알고 있습니다.__file__C c c c c c c c c c c c c. Mac에서는할 수 . Mac에서는 이렇게 할 수 있습니다.

>>> import collections #note that collections is a C extension in Python 2.5
>>> collections.__file__
'/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/lib-
dynload/collections.so'

단, 이로 인해 Windows 머신에서는 예외가 발생합니다.

은 이미 Python 2018으로 했습니다.__future__아주 오래 전에.Python 3.4와 함께 제공되는 놀라운 기능을 사용하여 문제를 해결하는 것은 어떨까요?os,os.path,glob ,shutil 등등.

여기에는 3가지 경로가 있습니다(복제될 수 있음).

  • mod_path: 단순한 도우미 스크립트의 경로입니다.
  • src_path: 복사 대기 중인 템플릿파일이 몇 개 포함되어 있습니다.
  • cwd: 현재 디렉토리, 이러한 템플릿파일의 수신처.

그리고 문제는 우리가 이 모든 것을 할 수혈할 수 있는src_path에 대한 상대 경로만 알고 있습니다.mod_path.

이제 이 문제를 놀라운 것으로 해결합시다.

# Hope you don't be imprisoned by legacy Python code :)
from pathlib import Path

# `cwd`: current directory is straightforward
cwd = Path.cwd()

# `mod_path`: According to the accepted answer and combine with future power
# if we are in the `helper_script.py`
mod_path = Path(__file__).parent
# OR if we are `import helper_script`
mod_path = Path(helper_script.__file__).parent

# `src_path`: with the future power, it's just so straightforward
relative_path_1 = 'same/parent/with/helper/script/'
relative_path_2 = '../../or/any/level/up/'
src_path_1 = (mod_path / relative_path_1).resolve()
src_path_2 = (mod_path / relative_path_2).resolve()

미래에는 그냥 그렇게 간단해.


또한 다음과 같이 템플릿파일을 선택, 체크 및 복사/이동 할 수 있습니다.

if src_path != cwd:
    # When we have different types of files in the `src_path`
    for template_path in src_path.glob('*.ini'):
        fname = template_path.name
        target = cwd / fname
        if not target.exists():
            # This is the COPY action
            with target.open(mode='wb') as fd:
                fd.write(template_path.read_bytes())
            # If we want MOVE action, we could use:
            # template_path.replace(target)

os.path.realpath에서는 부모

import sys,os
sys.path.append(os.path.realpath('..'))

된 된 바와

import os
dir = os.path.dirname(__file__)
filename = os.path.join(dir, '/relative/path/to/file/you/want')

나는 단지 그것을 덧붙이고 싶다.

후자의 문자열은 백슬래시로 시작할 수 없습니다.infact no 문자열에는 백슬래시를 포함할 수 없습니다.

뭐랄까...

import os
dir = os.path.dirname(__file__)
filename = os.path.join(dir, 'relative','path','to','file','you','want')

승인된 답변은 경우에 따라 오해를 일으킬 수 있습니다.자세한 내용은 이 링크를 참조하십시오.

내 코드를 고려:

import os


def readFile(filename):
    filehandle = open(filename)
    print filehandle.read()
    filehandle.close()



fileDir = os.path.dirname(os.path.realpath('__file__'))
print fileDir

#For accessing the file in the same folder
filename = "same.txt"
readFile(filename)

#For accessing the file in a folder contained in the current folder
filename = os.path.join(fileDir, 'Folder1.1/same.txt')
readFile(filename)

#For accessing the file in the parent folder of the current folder
filename = os.path.join(fileDir, '../same.txt')
readFile(filename)

#For accessing the file inside a sibling folder.
filename = os.path.join(fileDir, '../Folder2/same.txt')
filename = os.path.abspath(os.path.realpath(filename))
print filename
readFile(filename)

sys.path 프로그램 시작 시 초기화됨으로 이 목록의 첫 번째 항목 path[0]는 Python 인터프리터를 호출하는 데 사용된 스크립트를 포함하는 디렉터리입니다.

경로를 상대 경로를 적용할 루트 폴더로 사용합니다.

>>> import sys
>>> import os.path
>>> sys.path[0]
'C:\\Python25\\Lib\\idlelib'
>>> os.path.relpath(sys.path[0], "path_to_libs") # if you have python 2.6
>>> os.path.join(sys.path[0], "path_to_libs")
'C:\\Python25\\Lib\\idlelib\\path_to_libs'

사용하는 대신

import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

승인된 답변과 마찬가지로 다음을 사용하는 것이 더 강력합니다.

import inspect
import os
dirname = os.path.dirname(os.path.abspath(inspect.stack()[0][1]))
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

__file__을 사용하면 모듈이 로드된 파일이 파일에서 로드된 경우 반환되므로 스크립트가 포함된 파일이 다른 곳에서 호출된 경우 반환된 디렉토리가 올바르지 않습니다.

자세한 것은, https://stackoverflow.com/a/31867043/5542253 및 https://stackoverflow.com/a/50502/5542253 를 참조해 주세요.

다른 사용자 및 pathlib 문서에서 제시된 간단한(이상적이지 않은) 솔루션은 다음과 같습니다(참조할 필요가 있는 파일이 다음과 같다고 가정합니다).Test/data/users.csv

# Current file location: Tests/src/long/module/subdir/some_script.py
from pathlib import Path

# back to Tests/
PROJECT_ROOT = Path(__file__).parents[4]
# then down to Test/data/users.csv
CSV_USERS_PATH = PROJECT_ROOT / 'data' / 'users.csv'  

with CSV_USERS_PATH.open() as users:
    print(users.read())

만, 「」를 하면, .some_script.py프로젝트의 될 수 우리는 프로젝트의 ).parents[4]을 사용하다

같은 생각을 바탕으로 더 나은 해결책을 찾은 것 같아요.에는 파일 하겠습니다.paths.py프로젝트의 루트가 있는 위치를 저장하기 위해 이 파일은 루트 디렉토리와 비교하여 동일한 위치에 유지됩니다.

Tests
├── data
│  └── users.csv
└── src
   ├── long
   │  └── module
   │     └── subdir
   │        └── some_script.py
   ├── main.py
   └── paths.py

서 ★★★★★paths.py은 '''를 하는 것입니다PROJECT_ROOT:

from pathlib import Path

PROJECT_ROOT = Path(__file__).parents[1]

에서 ""를 사용할 수 되었습니다.paths.PROJECT_ROOT프로젝트의 루트에서 절대 경로를 표현합니다.를 들면, 「 」에서는,src/long/module/subdir/some_script.py을 사용하다

from paths import PROJECT_ROOT

CSV_USERS_PATH = PROJECT_ROOT / 'data' / 'users.csv'

def hello():
    with CSV_USERS_PATH.open() as f:
        print(f.read())

모든 것이 예상대로 진행됩니다.

~/Tests/src/$ python main.py

/Users/cglacet/Tests/data/users.csv
hello, user

~/Tests/$ python src/main.py

/Users/cglacet/Tests/data/users.csv
hello, user

main.py츠키다

from long.module.subdir import some_script

some_script.hello()

가장 중요한 명령어 요약

>>> import os
>>> os.path.join('/home/user/tmp', 'subfolder')
'/home/user/tmp/subfolder'
>>> os.path.normpath('/home/user/tmp/../test/..')
'/home/user'
>>> os.path.relpath('/home/user/tmp', '/home/user')
'tmp'
>>> os.path.isabs('/home/user/tmp')
True
>>> os.path.isabs('/tmp')
True
>>> os.path.isabs('tmp')
False
>>> os.path.isabs('./../tmp')
False
>>> os.path.realpath('/home/user/tmp/../test/..') # follows symbolic links
'/home/user'

상세한 것에 대하여는, 문서를 참조해 주세요.Linux 경로입니다.Windows도 마찬가지로 동작합니다.

먼저 os.path.abspath(path) os.path.relpath(path) 함수를 이해해야 합니다.

, os.path.abspath(path)는 절대 경로에 대한 상대 경로를 만듭니다.또한 제공된 경로가 절대 경로인 경우 함수는 동일한 경로를 반환합니다.

마찬가지로 os.path.relpath(path)는 상대 경로에 대한 절대 경로를 만듭니다.또한 제공된 경로가 상대 경로인 경우 함수는 동일한 경로를 반환합니다.

다음 예에서는 위의 개념을 올바르게 이해할 수 있습니다.

input_file_list 파일이 있다고 가정합니다.txt에는 python 스크립트로 처리할 입력 파일 목록이 포함되어 있습니다.

D:\conc\input1.dic

D:\conc\input2.dic

D:\Copyioconc\input_file_list.txt

위의 폴더 구조가 표시되면 input_file_list를 입력합니다.txtCopyofconc 폴더에 있고 python 스크립트로 처리할 파일은 conc 폴더에 있습니다.

그러나 input_file_list 파일의 내용은 다음과 같습니다.txt는 다음과 같습니다.

..\conc\input1.dic

..\conc\input2.dic

Python 스크립트는 D: 드라이브에 있습니다.

또한 input_file_list에 제공된 상대 경로입니다.txt 파일은 input_file_list 경로에 상대적입니다.txt 파일.

따라서 python 스크립트가 현재 작업 디렉토리를 실행할 때(os.getcwd()사용하여 경로를 가져옵니다).

상대 경로가 input_file_list에 상대 경로이기 때문입니다.txt, 즉 "D:\Copyofconc", 현재 작업 디렉토리를 "D:"로 변경해야 합니다.\Copyofconc"를 참조해 주세요.

os.chdir('D:\Copyofconc')는 현재 작업 디렉토리가 "D:\Copyofconc"를 참조해 주세요.

이제 input1.dic 및 input2.dic 파일을 가져오려면 "..\conc\input1.dic" 명령어를 사용합니다.

input1_path= os.path.abspathgroups..\conc\input1.dic') (상대 경로를 절대 경로로 변경합니다.현재 작업 디렉토리는 "D:\Copyofconc", 파일 ".\conc\input1.dic"은 "D:"에 대해 접근해야 합니다.\Copyofconc")

따라서 input1_path는 "D:\conc\input1.dic"이어야 합니다.

이 코드는 절대 경로를 기본 스크립트로 반환합니다.

import os
def whereAmI():
    return os.path.dirname(os.path.realpath(__import__("__main__").__file__))

이것은 모듈에서도 동작합니다.

나에게 적합한 대안:

this_dir = os.path.dirname(__file__) 
filename = os.path.realpath("{0}/relative/file.path".format(this_dir))


다음은 Python '3.9.5'에서 테스트한 예입니다.

" 재디디디: your your your your:'c:\project1\code\'
.'c:\project1\dataset\train\'
다음 이 수 주소는 다음과 .'../dataset/train/'

레퍼런스


은, 「 」를 해 주세요.path in Python 「 」 「 」

가 있었던 은 에에과 what what what를 사용한 것이다.sys.path.insert그런 다음 이동해야 할 디렉토리를 지정했습니다.예를 들어, 한 개의 디렉토리만 올라가면 됩니다.

import sys
sys.path.insert(0, '../')

모든 시스템에서 작동하려면 "os.path" 대신 "ntpath"를 사용합니다.현재는 Windows, Linux 및 Mac OSX에서 잘 작동합니다.

import ntpath
import os
dirname = ntpath.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

간단한 해결책은

import os
os.chdir(os.path.dirname(__file__))

부터C:\Users\xyz\myFolder로.C:\Users\xyz\testdata:

import os
working_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
# C:\Users\xyz\myFolder
print(working_dir)
updated_working_dir = os.path.join(os.path.realpath(working_dir + '/../'), 'testdata')
# C:\Users\xyz\testdata
print(updated_working_dir)

산출량

C:\Users\xyz\myFolder
C:\Users\xyz\testdata

제 요약은 다음과 같습니다.

먼저 툴 함수를 정의합니다.relpath현재 파일에 대한 상대 경로를 cwd에 대한 상대 경로로 변환합니다.

import os
relpath = lambda p: os.path.normpath(os.path.join(os.path.dirname(__file__), p))

그런 다음 현재 파일에 상대적인 경로를 래핑하는 데 사용합니다.

path1 = relpath('../src/main.py')

전화도 할 수 요.sys.path.append() 을 Import하다

sys.path.append(relpath('..')) # so that you can import from upper dir

완전한 코드 예:https://gist.github.com/luochen1990/9b1ffa30f5c4a721dab5991e040e3eb1

"Helper"라는 이름의 현재 아카이브와 "Workshop"이라는 이름의 상위 디렉토리와 템플릿 파일이 \Workshop에 있다고 가정합니다.\Templates, 그러면 Python의 상대 경로는 "..\Templates" 입니다.

이는 시스템 경로세트에 상대 경로를 추가하는 간단한 방법입니다.예를 들어, 타겟디렉토리가 한 레벨 위(따라서,'/../'「 」 「 」:

import os
import sys
workingDir = os.getcwd()
targetDir = os.path.join(os.path.relpath(workingDir + '/../'),'target_directory')
sys.path.insert(0,targetDir)

이 솔루션의 테스트 대상:

Python 3.9.6 | conda-forge 패키지화 | (디폴트, 2021년 7월 11일 03:37:25) [MSC v.1916 64비트(AMD64)]

일부 이전 버전에 적용되는지는 모르겠지만 Python 3.3은 상대 경로를 기본적으로 지원합니다.

예를 들어 다음 코드는 python 스크립트와 동일한 폴더에 텍스트 파일을 생성해야 합니다.

open("text_file_name.txt", "w+t")

(상대 경로일 경우 처음에 순방향 또는 백슬래시가 없어야 합니다.)

언급URL : https://stackoverflow.com/questions/918154/relative-paths-in-python

반응형