패키지에있는 Python 모듈의 이름을 나열하는 표준 방법이 있습니까?


101

사용하지 않고 패키지의 모든 모듈 이름을 나열하는 간단한 방법이 __all__있습니까?

예를 들어 다음 패키지가 제공됩니다.

/testpkg
/testpkg/__init__.py
/testpkg/modulea.py
/testpkg/moduleb.py

다음과 같은 작업을 수행하는 표준 또는 기본 제공 방법이 있는지 궁금합니다.

>>> package_contents("testpkg")
['modulea', 'moduleb']

수동 접근 방식은 패키지의 디렉토리를 찾기 위해 모듈 검색 경로를 반복하는 것입니다. 그런 다음 해당 디렉토리의 모든 파일을 나열하고 고유 한 이름의 py / pyc / pyo 파일을 필터링하고 확장명을 제거하고 해당 목록을 반환 할 수 있습니다. 그러나 이것은 모듈 가져 오기 메커니즘이 이미 내부적으로 수행하고있는 작업에 상당한 양의 작업처럼 보입니다. 그 기능이 어디에나 노출되어 있습니까?

답변:


23

아마도 이것이 당신이 찾고있는 것을 할 것입니까?

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

1
init .py는 실제로 패키지의 일부가 아니기 때문에 마지막 'if' 에 'and module! = " init .py"'를 추가합니다 . 그리고 .pyo는 또 다른 유효한 확장자입니다. 그 외에도 imp.find_module을 사용하는 것은 정말 좋은 생각입니다. 이것이 정답이라고 생각합니다.
— DNS

3
동의하지 않습니다. init를 직접 가져올 수 있는데 왜 특별한 경우입니까? 규칙을 어길만큼 특별하지는 않습니다. ;-)
— cdleary

6
imp.get_suffixes()손으로 쓴 목록 대신 사용하는 것이 좋습니다.
— itsadok

3
또한, 음이 같은 서브 패키지에 작동하지 않습니다xml.sax
— itsadok

1
이것은 정말 나쁜 방법입니다. 파일 이름 확장자에서 모듈이 무엇인지 확실하게 알 수 없습니다.
— WIM

189

사용 python2.3를 이상 , 당신은 또한 사용할 수있는 pkgutil모듈을 :

>>> import pkgutil
>>> [name for _, name, _ in pkgutil.iter_modules(['testpkg'])]
['modulea', 'moduleb']

편집 : 매개 변수는 모듈 목록이 아니라 경로 목록이므로 다음과 같이 할 수 있습니다.

>>> import os.path, pkgutil
>>> import testpkg
>>> pkgpath = os.path.dirname(testpkg.__file__)
>>> print [name for _, name, _ in pkgutil.iter_modules([pkgpath])]

15
이것은 문서화되어 있지 않지만 가장 정확한 방법 인 것 같습니다. 내가 메모를 추가해도 상관 없습니다.
— itsadok

13
pkgutil에가 python2.3 최대 사실 . 반면 또한, pkgutil.iter_modules()재귀 적으로 작동하지 않습니다하는을가 pkgutil.walk_packages()한다,뿐만 아니라 것입니다 재귀. 이 패키지에 대한 포인터를 주셔서 감사합니다.
— Sandip Bhattacharya

iter_modules절대 가져 오기에서 작동하지 않는 이유 는 무엇 a.b.testpkg입니까? 그것은 저를주고있다[]
— 후세인

나는 당신의 편집을 간과했습니다 :(. 죄송합니다. 두 번째 스 니펫을 따랐을 때 작동합니다.
— Hussain

1
pkgutil.walk_packages()반복 되는 것을 확인할 수 없으며 .와 동일한 출력을 제공 pkgutil.iter_modules()하므로 대답이 불완전하다고 생각합니다.
— rwst

29
import module
help(module)

2
도움말은 도움말 텍스트의 맨 아래에 패키지 내용을 나열하지만 문제는 f (package_name) => [ "module1_name", "module2_name"]과 같은 방법에 대한 자세한 내용입니다. 도움말에서 반환 한 문자열을 구문 분석 할 수 있다고 가정하지만 디렉토리를 나열하는 것보다 더 둥글게 보입니다.
— DNS

1
@DNS : help()물건을 인쇄하고 문자열을 반환하지 않습니다.
— Junuxx

나는 이것이 로터리 길이라는 데 동의하지만 어떻게 help()작동 하는지 확인하기 위해 토끼 구멍을 보냈습니다 . 어쨌든, 내장 pydoc모듈은 help()페이지 를 매기 는 문자열을 뱉어내는 데 도움이 될 수 있습니다 : import pydoc; pydoc.render_doc('mypackage').
— sraboy

8

내가 무언가를 간과하고 있는지 또는 답변이 오래된 것인지는 모르겠지만;

user815423426이 언급했듯이 이것은 라이브 객체에 대해서만 작동하며 나열된 모듈은 이전에 가져온 모듈 일뿐입니다.

inspect를 사용하면 패키지에 모듈을 나열하는 것이 정말 쉬워 보입니다 .

>>> import inspect, testpkg
>>> inspect.getmembers(testpkg, inspect.ismodule)
['modulea', 'moduleb']

import = import __ ( 'myproj.mymod.mysubmod') m = inspect.getmembers (i, inspect.ismodule) 넣었지만 가져온 경로는 ~ / myproj / __ init .py이고 m은 (mymod, '~ /myproj/mymod/__init__.py ')
— hithwen

1
@hithwen 댓글에 질문하지 마세요. 특히 직접 관련이없는 경우에는 질문하지 마세요. 선한 사마리아인되기 : imported = import importlib; importlib.import_module('myproj.mymod.mysubmod'). __import__최상위 모듈을 가져옵니다 . 설명서를 참조하십시오 .
— siebz0r 2013

흠, 이것은 유망하지만 나를 위해 작동하지 않습니다. 내가 할 때 import inspect, mypackage다음 inspect.getmembers(my_package, inspect.ismodule)나는 확실히에서 다양한 모듈을 가지고에도 불구하고, 빈 목록을 가져옵니다.
— Amelio Vazquez-Reina

1
사실, 이것은 단지 나는 경우 작동하는 것 같다 import my_package.foo뿐 아니라 import mypackage,이 경우 그 다음 수익률 foo. 그러나 이것은 목적
— Amelio Vazquez-Reina

3
@ user815423426 당신이 절대적으로 맞습니다 ;-) 내가 뭔가를 간과하고 있었던 것 같습니다.
— siebz0r 2013-06-26

3

이것은 파이썬 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

os.scandir결과 항목을 직접 반복하는 대신 컨텍스트 관리자로 사용하는 이점은 무엇입니까 ?
— monkut

1
참조 @monkut docs.python.org/3/library/os.html#os.scandir 이가 보장하는 컨텍스트 매니저로 사용하는 것이 좋습니다 close당신은 어떤 보류 자원이 해제되는 것을 보장하기 위해 함께 할 때 호출된다.
— tacaswell

이 나던 작품은 re대신 모든 패키지를 나열하지만, 추가 re.그들 모두에
— Tushortz

1

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)

0

모듈이 나열되어야합니다.

help("modules")

0

명령 프롬프트에서 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>)

-2
def package_contents(package_name):
  package = __import__(package_name)
  return [module_name for module_name in dir(package) if not module_name.startswith("__")]

패키지가 아닌 모듈에서만 작동합니다. logging내가 의미하는 바를 보려면 Python의 패키지 에서 사용해보십시오 . 로깅에는 핸들러와 구성의 두 가지 모듈이 있습니다. 코드는 두 이름을 포함하지 않는 66 개 항목의 목록을 반환합니다.
— DNS

-3

print dir (모듈)


1
이미 가져온 모듈의 내용이 나열됩니다. 모든 것이 지정되지 않은 경우 'from x import *'와 마찬가지로 아직 가져 오지 않은 패키지의 내용을 나열하는 방법을 찾고 있습니다.
— DNS

from x import *는 먼저 모듈을 가져온 다음 모든 것을 현재 모듈에 복사합니다.
— Seb

Windows의 대소 문자 구분 문제로 인해 'from x import *'는 실제로 패키지의 하위 모듈을 가져 오지 않는다는 것을 깨달았습니다. 저는 제가하고 싶은 일의 예로만 포함 시켰습니다. 혼란을 피하기 위해 질문에서 편집했습니다.
— DNS

여기에는 하위 모듈 목록 만이 아니라 이미 가져온 개체의 모든 속성이 나열됩니다. 그래서 그것은 질문에 답하지 않습니다.
— bignose 2010-01-29
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.