패키지에있는 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.