argparse가있는 디렉토리 경로 유형
내 파이썬 스크립트는 명령 줄에 전달 된 디렉토리에서 파일을 읽어야합니다. 명령 줄에 전달 된 디렉터리가 존재하고 읽을 수 있는지 확인하기 위해 argparse와 함께 사용하도록 아래와 같이 Readable_dir 유형을 정의했습니다. 또한 기본값 (아래 예의 / tmp / non_existent_dir)도 디렉토리 인수에 지정되었습니다. 여기서 문제는 argparse가 명령 줄에서 디렉토리 인수가 명시 적으로 전달되는 상황에서도 기본값으로 Readable_dir ()을 호출한다는 것입니다. 이로 인해 명령 줄에서 디렉토리가 명시 적으로 전달되는 컨텍스트에 기본 경로 / tmp / non_existent_dir이 존재하지 않으므로 스크립트가 중단됩니다. 기본값을 지정하지 않고이 인수를 필수로 설정하여이 문제를 해결할 수 있습니다.
#!/usr/bin/python
import argparse
import os
def readable_dir(prospective_dir):
if not os.path.isdir(prospective_dir):
raise Exception("readable_dir:{0} is not a valid path".format(prospective_dir))
if os.access(prospective_dir, os.R_OK):
return prospective_dir
else:
raise Exception("readable_dir:{0} is not a readable dir".format(prospective_dir))
parser = argparse.ArgumentParser(description='test', fromfile_prefix_chars="@")
parser.add_argument('-l', '--launch_directory', type=readable_dir, default='/tmp/non_existent_dir')
args = parser.parse_args()
유형 대신 사용자 지정 작업을 만들 수 있습니다.
import argparse
import os
import tempfile
import shutil
import atexit
class readable_dir(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
prospective_dir=values
if not os.path.isdir(prospective_dir):
raise argparse.ArgumentTypeError("readable_dir:{0} is not a valid path".format(prospective_dir))
if os.access(prospective_dir, os.R_OK):
setattr(namespace,self.dest,prospective_dir)
else:
raise argparse.ArgumentTypeError("readable_dir:{0} is not a readable dir".format(prospective_dir))
ldir = tempfile.mkdtemp()
atexit.register(lambda dir=ldir: shutil.rmtree(ldir))
parser = argparse.ArgumentParser(description='test', fromfile_prefix_chars="@")
parser.add_argument('-l', '--launch_directory', action=readable_dir, default=ldir)
args = parser.parse_args()
print (args)
그러나 이것은 나에게 약간 수상한 것처럼 보입니다. 디렉토리가 제공되지 않으면 처음에 디렉토리에 액세스 할 수 있는지 확인하는 목적을 무력화하는 것처럼 보이는 읽을 수없는 디렉토리를 전달합니다.
코멘트에 지적 밖으로, 그것은가 좋을 수도 있습니다 raise argparse.ArgumentError(self, ...)
보다는 argparse.ArgumentTypeError
.
편집하다
내가 아는 한 기본 인수의 유효성을 검사 할 방법이 없습니다. 나는 가정 argparse
개발자 당신이 기본을 제공하는 경우, 다음이 유효해야한다고 생각했습니다. 여기서 가장 빠르고 쉬운 방법은 인수를 구문 분석 한 후 즉시 유효성을 검사하는 것입니다. 작업을 수행하기 위해 임시 디렉토리를 얻으려는 것 같습니다. 이 경우 tempfile
모듈을 사용하여 새 디렉터리를 가져올 수 있습니다 .이를 반영하기 위해 위의 답변을 업데이트했습니다. 임시 디렉터리를 만들고 기본 인수로 사용하고 ( tempfile
이미 생성 한 디렉터리가 쓰기 가능함을 보장 함) 프로그램이 종료 될 때 삭제되도록 등록합니다.
몇 달 전에 파이썬 표준 라이브러리 메일 링리스트에 "경로 인수"에 대한 패치를 제출 했습니다 .
이 PathType
클래스를 사용하면 다음 인수 유형을 지정하여 기존 디렉토리 만 일치시킬 수 있습니다 . 다른 모든 항목은 오류 메시지를 표시합니다.
type = PathType(exists=True, type='dir')
다음은 특정 파일 / 디렉토리 권한을 요구하도록 쉽게 수정할 수있는 코드입니다.
from argparse import ArgumentTypeError as err
import os
class PathType(object):
def __init__(self, exists=True, type='file', dash_ok=True):
'''exists:
True: a path that does exist
False: a path that does not exist, in a valid parent directory
None: don't care
type: file, dir, symlink, None, or a function returning True for valid paths
None: don't care
dash_ok: whether to allow "-" as stdin/stdout'''
assert exists in (True, False, None)
assert type in ('file','dir','symlink',None) or hasattr(type,'__call__')
self._exists = exists
self._type = type
self._dash_ok = dash_ok
def __call__(self, string):
if string=='-':
# the special argument "-" means sys.std{in,out}
if self._type == 'dir':
raise err('standard input/output (-) not allowed as directory path')
elif self._type == 'symlink':
raise err('standard input/output (-) not allowed as symlink path')
elif not self._dash_ok:
raise err('standard input/output (-) not allowed')
else:
e = os.path.exists(string)
if self._exists==True:
if not e:
raise err("path does not exist: '%s'" % string)
if self._type is None:
pass
elif self._type=='file':
if not os.path.isfile(string):
raise err("path is not a file: '%s'" % string)
elif self._type=='symlink':
if not os.path.symlink(string):
raise err("path is not a symlink: '%s'" % string)
elif self._type=='dir':
if not os.path.isdir(string):
raise err("path is not a directory: '%s'" % string)
elif not self._type(string):
raise err("path not valid: '%s'" % string)
else:
if self._exists==False and e:
raise err("path exists: '%s'" % string)
p = os.path.dirname(os.path.normpath(string)) or '.'
if not os.path.isdir(p):
raise err("parent path is not a directory: '%s'" % p)
elif not os.path.exists(p):
raise err("parent directory does not exist: '%s'" % p)
return string
스크립트가 유효하지 않으면 작동하지 않으면 launch_directory
필수 인수로 만들어야합니다.
parser.add_argument('launch_directory', type=readable_dir)
BTW, 당신은 사용해야하는 argparse.ArgumentTypeError
대신 Exception
에서 readable_dir()
.
참조 URL : https://stackoverflow.com/questions/11415570/directory-path-types-with-argparse
'programing' 카테고리의 다른 글
두 로컬 저장소 간의 변경 사항을 가져 오는 힘내 (0) | 2021.01.08 |
---|---|
C에서 유니 코드 문자열의 문자를 계산하는 방법 (0) | 2021.01.08 |
NOP 썰매는 어떻게 작동합니까? (0) | 2021.01.08 |
오류가 발생하는 이유… 예기치 않은 요청 : GET / internalapi / quotes (0) | 2021.01.08 |
Xamarin Forms에서 푸시 알림을 사용하는 방법 (0) | 2021.01.08 |