코드베이스의 몇 가지 템플릿 파일을 현재 디렉토리로 복사하는 간단한 도우미 스크립트를 작성 중입니다. 그러나 템플릿이 저장된 디렉토리의 절대 경로는 없습니다. 스크립트에서 상대 경로가 있지만 스크립트를 호출하면 현재 작업 디렉토리에 상대적인 경로로 처리합니다. 이 상대 URL이 대신 스크립트의 위치에서 오도록 지정하는 방법이 있습니까?
코드베이스의 몇 가지 템플릿 파일을 현재 디렉토리로 복사하는 간단한 도우미 스크립트를 작성 중입니다. 그러나 템플릿이 저장된 디렉토리의 절대 경로는 없습니다. 스크립트에서 상대 경로가 있지만 스크립트를 호출하면 현재 작업 디렉토리에 상대적인 경로로 처리합니다. 이 상대 URL이 대신 스크립트의 위치에서 오도록 지정하는 방법이 있습니까?
답변:
스크립트가있는 파일에서 다음과 같은 작업을 수행하려고합니다.
import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')
이것은 당신이 찾고있는 파일의 절대 경로를 줄 것입니다. setuptools를 사용하는 경우 패키지 자원 API를 대신 사용해야 합니다.
업데이트 : 여기에 주석에 응답하여 코드 샘플을 붙여 넣을 수 있습니다. :-)
__file__
항상 사용할 수 있는 것은 아니라고 생각하는 것이 맞 습니까 (예 : 파일을 가져 오는 대신 직접 실행하는 경우)?
__main__
파일을 직접 실행한다고 언급 할 때 스크립트 를 의미한다고 가정합니다 . 그렇다면 내 시스템 (OS X 10.5.7의 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 확장에 몇 가지 단점이 있다는 것을 알고 있습니다. 예를 들어, 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 컴퓨터에서 예외를 발생시킵니다.
filename = os.path.join(dir, 'relative', 'path', 'to', 'file', 'you' , 'want')
os.path.dirname(__file__)
빈 문자열을 줄 수 있습니다. os.path.dirname(os.path.abspath(__file__))
대신 사용하십시오
필요합니다 os.path.realpath
(아래 샘플은 상위 디렉토리를 경로에 추가합니다)
import sys,os
sys.path.append(os.path.realpath('..'))
os.path.dirname(__file__)
빈 줄을 줬어 이것은 완벽하게 작동했습니다.
os.path.realpath('..')
현재 작업 디렉토리의 상위 디렉토리를 제공합니다 . 그것은 일반적으로 당신이 원하는 것이 아닙니다 .
허용 된 답변에서 언급했듯이
import os
dir = os.path.dirname(__file__)
filename = os.path.join(dir, '/relative/path/to/file/you/want')
그냥 추가하고 싶습니다
후자의 문자열은 백 슬래시로 시작할 수 없습니다. 실제로 어떤 문자열도 백 슬래시를 포함해서는 안됩니다
다음과 같아야합니다
import os
dir = os.path.dirname(__file__)
filename = os.path.join(dir, 'relative','path','to','file','you','want')
경우에 따라 허용 된 답변이 잘못 될 수 있습니다. 자세한 내용은 이 링크를 참조하십시오
os.path.join
OS 별 구분 기호와 결합 하여 사용하는 것이 좋습니다.
'/relative/path...'
상대 경로가 아닙니다. 의도적인가요?
os.path.join()
. 남은 것은 경로 구분자를 하드 코딩하는 것보다 각 경로 요소마다 별도의 문자열을 사용하는 것입니다.
이제 2018 년이며 Python은 이미 __future__
오래 전에 진화했습니다 . 어떻게 놀라운 사용에 대한 pathlib
작업을 수행하기 위해 파이썬 3.4와 함께 오는 대신에 어려움을 겪고 os
, os.path
, glob
, shutil
, 등
따라서 여기에 3 개의 경로가 있습니다 (아마도 복제 됨).
mod_path
: 간단한 도우미 스크립트 의 경로입니다.src_path
: 복사 대기중인 두 개의 템플릿 파일 이 들어 있습니다.cwd
: 현재 디렉토리 , 해당 템플리트 파일의 대상그리고 문제는 : 우리는없는 의 전체 경로를 src_path
만 알고 그것의 상대 경로 받는 사람을 mod_path
.
이제이 놀라운 문제를 해결해 보자 pathlib
.
# 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()
앞으로는 그렇게 간단합니다. :디
또한 다음을 사용하여 템플릿 파일을 선택하고 확인하고 복사 / 이동할 수 있습니다 pathlib
.
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)
내 코드를 고려하십시오.
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'
sys.path[0]
항상 상위 디렉토리로 설정되어 있지는 않습니다. 파이썬 코드로 호출 할 수 있습니다 -c
또는 -m
또는 지점이있는 임베디드 통역을 통해 sys.path[0]
모두 뭔가 다른 설정됩니다.
사용하는 대신
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에 대한 자세한 정보를 제공합니다.
inspect.stack()
호출 하는 데 비싼 기능입니다. 모든 스택 프레임에 대한 정보를 검색 한 다음 버리고 최상위 프레임 만 가져옵니다. 기본적으로 inspect.getfile()
모듈 객체를 호출 합니다 module.__file__
. 을 사용하는 것이 훨씬 낫습니다 __file__
.
안녕하십니까 우선 os.path.abspath (path) 및 os.path.relpath (path) 함수를 이해해야합니다.
간단히 말해서 os.path.abspath (path) 는 절대 경로에 대한 상대 경로 를 만듭니다. . 제공된 경로 자체가 절대 경로이면 함수는 동일한 경로를 반환합니다.
비슷하게 os.path.relpath (path) 는 상대 경로에 대한 절대 경로 를 만듭니다 . 제공된 경로 자체가 상대 경로이면 함수는 동일한 경로를 반환합니다.
아래 예제는 위의 개념을 올바르게 이해하도록 할 수 있습니다 .
파이썬 스크립트로 처리 할 입력 파일 목록이 들어있는 input_file_list.txt 파일이 있다고 가정하십시오 .
D : \ conc \ input1.dic
D : \ conc \ input2.dic
D : \ Copyioconc \ input_file_list.txt
위의 폴더 구조 를 보면 copy_conc 폴더 에 input_file_list.txt 가 있고 파이썬 스크립트로 처리 할 파일은 conc에 있습니다 폴더에 있습니다
그러나 input_file_list.txt 파일의 내용은 다음과 같습니다.
.. \ conc \ input1.dic
.. \ conc \ input2.dic
그리고 내 파이썬 스크립트는 D : 드라이브에 있습니다.
그리고에서 제공하는 상대 경로 input_file_list.txt 파일의 경로를 기준으로 input_file_list.txt 파일.
따라서 파이썬 스크립트가 현재 작업 디렉토리를 실행할 때 ( 경로를 얻으려면 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.abspath ( '.. \ 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__))
이것은 모듈에서도 작동합니다.
sys.modules['__main__'].__file__
합니다.
나를 위해 일한 것은을 사용하고 sys.path.insert
있습니다. 그런 다음 이동해야 할 디렉토리를 지정했습니다. 예를 들어 방금 하나의 디렉토리로 올라 가야했습니다.
import sys
sys.path.insert(0, '../')
이것이 이전 버전 중 일부에 적용되는지 확실하지 않지만 Python 3.3에는 기본 상대 경로 지원이 있다고 생각합니다.
예를 들어 다음 코드는 python 스크립트와 동일한 폴더에 텍스트 파일을 작성해야합니다.
open("text_file_name.txt", "w+t")
(상대 경로 인 경우 처음에 앞으로 또는 백 슬래시가 없어야합니다.)