패키지에 파이썬 모듈의 이름을 나열하는 표준 방법이 있습니까?
패키지에 포함된 모든 모듈의 이름을 쉽게 나열할 수 있는 방법이 있습니까?__all__
?
예를 들어, 이 패키지를 지정하면 다음과 같습니다.
/testpkg
/testpkg/__init__.py
/testpkg/modulea.py
/testpkg/moduleb.py
다음과 같은 작업을 수행할 수 있는 표준 또는 내장된 방법이 있는지 궁금합니다.
>>> package_contents("testpkg")
['modulea', 'moduleb']
수동 접근 방식은 패키지의 디렉터리를 찾기 위해 모듈 검색 경로를 반복하는 것입니다.그런 다음 해당 디렉터리의 모든 파일을 나열하고, 고유한 이름의 py/pyc/pypo 파일을 필터링하여 확장자를 제거한 후 해당 목록을 반환할 수 있습니다.그러나 이것은 모듈 가져오기 메커니즘이 내부적으로 이미 수행하고 있는 작업에 상당한 양의 작업으로 보입니다.그 기능이 어디에 노출됩니까?
python2.3 이상을 사용하면 다음을 사용할 수도 있습니다.pkgutil
모듈:
>>> import pkgutil
>>> [name for _, name, _ in pkgutil.iter_modules(['testpkg'])]
['modulea', 'moduleb']
편집: 다음에 대한 매개 변수에 주의하십시오.pkgutil.iter_modules
는 모듈 목록이 아니라 경로 목록이므로 다음과 같은 작업을 수행할 수 있습니다.
>>> import os.path, pkgutil
>>> import testpkg
>>> pkgpath = os.path.dirname(testpkg.__file__)
>>> print([name for _, name, _ in pkgutil.iter_modules([pkgpath])])
import module
help(module)
이것이 당신이 찾고 있는 것을 할 수 있을까요?
import imp
import os
MODULE_EXTENSIONS = ('.py', '.pyc', '.pyo')
def package_contents(package_name):
file, pathname, description = imp.find_module(package_name)
if file:
raise ImportError('Not a package: %r', package_name)
# Use a set because some may be both source and compiled.
return set([os.path.splitext(module)[0]
for module in os.listdir(pathname)
if module.endswith(MODULE_EXTENSIONS)])
제가 간과하고 있는 것인지, 아니면 답이 단지 구식인지는 모르겠지만;
사용자 815423426에 따르면 이 기능은 활성 개체에만 적용되며 나열된 모듈은 이전에 가져온 모듈만 해당됩니다.
검사를 사용하면 패키지에 모듈을 나열하는 것이 매우 쉬워 보입니다.
>>> import inspect, testpkg
>>> inspect.getmembers(testpkg, inspect.ismodule)
['modulea', 'moduleb']
이 버전은 python 3.6 이상에서 작동하는 재귀 버전입니다.
import importlib.util
from pathlib import Path
import os
MODULE_EXTENSIONS = '.py'
def package_contents(package_name):
spec = importlib.util.find_spec(package_name)
if spec is None:
return set()
pathname = Path(spec.origin).parent
ret = set()
with os.scandir(pathname) as entries:
for entry in entries:
if entry.name.startswith('__'):
continue
current = '.'.join((package_name, entry.name.partition('.')[0]))
if entry.is_file():
if entry.name.endswith(MODULE_EXTENSIONS):
ret.add(current)
elif entry.is_dir():
ret.add(current)
ret |= package_contents(current)
return ret
여기에는 다음 모듈이 나열됩니다.
help("modules")
있습니다.__loader__
각 패키지 인스턴스 내부의 변수입니다.따라서 패키지를 가져오면 패키지 내부의 "모듈 리소스"를 찾을 수 있습니다.
import testpkg # change this by your package name
for mod in testpkg.__loader__.get_resource_reader().contents():
print(mod)
물론 루프를 개선하여 "모듈" 이름을 찾을 수 있습니다.
import testpkg
from pathlib import Path
for mod in testpkg.__loader__.get_resource_reader().contents():
# You can filter the name like
# Path(l).suffix not in (".py", ".pyc")
print(Path(mod).stem)
패키지 내부에서 직접 사용하여 모듈을 찾을 수 있습니다.__loader__
물론이야.
명령 프롬프트에서 python 코드 외부의 패키지에 대한 정보를 보려면 pydoc을 사용하면 됩니다.
# get a full list of packages that you have installed on you machine
$ python -m pydoc modules
# get information about a specific package
$ python -m pydoc <your package>
Pydoc과 동일한 결과가 나오지만 통역사 내부에서는 도움말을 사용합니다.
>>> import <my package>
>>> help(<my package>)
cdleary의 예를 바탕으로 모든 하위 모듈에 대한 재귀 버전 목록 경로는 다음과 같습니다.
import imp, os
def iter_submodules(package):
file, pathname, description = imp.find_module(package)
for dirpath, _, filenames in os.walk(pathname):
for filename in filenames:
if os.path.splitext(filename)[1] == ".py":
yield os.path.join(dirpath, filename)
여기에 있는 다른 답변은 패키지를 검사할 때 패키지에서 코드를 실행합니다.만약 당신이 그것을 원하지 않는다면, 당신은 다음과 같은 대답으로 파일을 grep할 수 있습니다.
def _get_class_names(file_name: str) -> List[str]:
"""Get the python class name defined in a file without running code
file_name: the name of the file to search for class definitions in
return: all the classes defined in that python file, empty list if no matches"""
defined_class_names = []
# search the file for class definitions
with open(file_name, "r") as file:
for line in file:
# regular expression for class defined in the file
# searches for text that starts with "class" and ends with ( or :,
# whichever comes first
match = re.search("^class(.+?)(\(|:)", line) # noqa
if match:
# add the cleaned match to the list if there is one
defined_class_name = match.group(1).strip()
defined_class_names.append(defined_class_name)
return defined_class_names
@Metal3d 답변을 완료하려면 예, 할 수 있습니다.testpkg.__loader__.get_resource_reader().contents()
를 "가 "로더"인할 수 ._frozen_importlib_external.SourceFileLoader object
.
그나라가져경우온를리러로 라이브러리를 가져온 zipimport
하려면), 는 (ex: 메에패로드면로려)입니다.zipimporter object
그리고 그것들get_resource_reader
함수는 importlib과 다릅니다. "fullname" 인수가 필요합니다.
을 지정하면 .get_resource_reader
:
# An example with CrackMapExec tool
import importlib
import cme.protocols as cme_protocols
class ProtocolLoader:
def get_protocols(self):
protocols = {}
protocols_names = [x for x in cme_protocols.__loader__.get_resource_reader("cme.protocols").contents()]
for prot_name in protocols_names:
prot = importlib.import_module(f"cme.protocols.{prot_name}")
protocols[prot_name] = prot
return protocols
def package_contents(package_name):
package = __import__(package_name)
return [module_name for module_name in dir(package) if not module_name.startswith("__")]
언급URL : https://stackoverflow.com/questions/487971/is-there-a-standard-way-to-list-names-of-python-modules-in-a-package
'programing' 카테고리의 다른 글
개체 속성으로 어레이에서 개체 제거 (0) | 2023.07.25 |
---|---|
키/값 JavaScript 개체의 키를 가져오는 방법 (0) | 2023.07.25 |
페르시아/아랍 숫자를 영어 숫자로 변환 (0) | 2023.07.25 |
페이지 요청 생성자가 더 이상 사용되지 않습니다. (0) | 2023.07.25 |
MapStruct - 구현을 찾을 수 없습니다. (0) | 2023.07.25 |