파이썬 패키지의 일부인 모든 모듈을 찾는 간단한 방법이 있습니까? 나는 이 오래된 토론을 찾았 는데, 이것은 실제로 결정적이지는 않지만 os.listdir ()을 기반으로 한 내 자신의 솔루션을 출시하기 전에 확실한 답을 얻고 싶습니다.
파이썬 패키지의 일부인 모든 모듈을 찾는 간단한 방법이 있습니까? 나는 이 오래된 토론을 찾았 는데, 이것은 실제로 결정적이지는 않지만 os.listdir ()을 기반으로 한 내 자신의 솔루션을 출시하기 전에 확실한 답을 얻고 싶습니다.
답변:
예, 기반 pkgutil
또는 이와 유사한 것을 원합니다. 이렇게하면 달걀이나 zip 형식에 관계없이 모든 패키지를 똑같이 처리 할 수 있습니다 (os.listdir이 도움이되지 않는 경우).
import pkgutil
# this is the package we are inspecting -- for example 'email' from stdlib
import email
package = email
for importer, modname, ispkg in pkgutil.iter_modules(package.__path__):
print "Found submodule %s (is a package: %s)" % (modname, ispkg)
가져 오는 방법도? __import__
정상적으로 사용할 수 있습니다 .
import pkgutil
# this is the package we are inspecting -- for example 'email' from stdlib
import email
package = email
prefix = package.__name__ + "."
for importer, modname, ispkg in pkgutil.iter_modules(package.__path__, prefix):
print "Found submodule %s (is a package: %s)" % (modname, ispkg)
module = __import__(modname, fromlist="dummy")
print "Imported", module
importer
의해 반환 pkgutil.iter_modules
됩니까? 이 "해커"처럼 보이는 대신 모듈을 가져 오는 데 사용할 수 있습니까 __import__(modname, fromlist="dummy")
?
m = importer.find_module(modname).load_module(modname)
다음과 같이 importer를 사용할 수있었습니다 : 그리고 m
모듈입니다. 예를 들면 :m.myfunc()
_path_
. 양쪽에 2 개, 총 4 개 (예 :)가 있어야합니다 __path__
.
이 작업에 적합한 도구는 pkgutil.walk_packages입니다.
시스템의 모든 모듈을 나열하려면 :
import pkgutil
for importer, modname, ispkg in pkgutil.walk_packages(path=None, onerror=lambda x: None):
print(modname)
walk_packages는 모든 하위 패키지를 가져 오지만 하위 모듈은 가져 오지 않습니다.
특정 패키지의 모든 하위 모듈을 나열하려면 다음과 같이 사용할 수 있습니다.
import pkgutil
import scipy
package=scipy
for importer, modname, ispkg in pkgutil.walk_packages(path=package.__path__,
prefix=package.__name__+'.',
onerror=lambda x: None):
print(modname)
iter_modules는 한 수준 깊이의 모듈 만 나열합니다. walk_packages는 모든 하위 모듈을 가져옵니다. 예를 들어 scipy의 경우 walk_packages는
scipy.stats.stats
iter_modules는
scipy.stats
pkgutil ( http://docs.python.org/library/pkgutil.html ) 에 대한 문서 에는 /usr/lib/python2.6/pkgutil.py에 정의 된 흥미로운 함수가 모두 나열되어 있지 않습니다.
아마도 이것은 기능이 "공용"인터페이스의 일부가 아니며 변경 될 수 있음을 의미합니다.
그러나 적어도 Python 2.6 (및 이전 버전?)에서 pkgutil에는 사용 가능한 모든 모듈을 반복적으로 안내하는 walk_packages 메서드가 제공됩니다.
walk_packages
이제 문서에 있습니다 : docs.python.org/library/pkgutil.html#pkgutil.walk_packages
_
) 전후 path
-되어 사용package.__path__
하기보다는 package._path_
. 코드를 다시 입력하는 것보다 잘라서 붙여 넣는 것이 더 쉬울 수 있습니다.
package
가 모듈이 아닌 패키지를 가리키는 지 확인하십시오 . 모듈은 파일이고 패키지는 디렉토리입니다. 모든 패키지에는 __path__
속성이 있습니다 (... 누군가가 어떤 이유로 속성을 삭제하지 않는 한)
내 패키지에서 편집중인 모든 하위 모듈을 라이브로 다시로드하는 방법을 찾고있었습니다. 위의 답변 / 댓글의 조합이므로 댓글이 아닌 답변으로 여기에 게시하기로 결정했습니다.
package=yourPackageName
import importlib
import pkgutil
for importer, modname, ispkg in pkgutil.walk_packages(path=package.__path__, prefix=package.__name__+'.', onerror=lambda x: None):
try:
modulesource = importlib.import_module(modname)
reload(modulesource)
print("reloaded: {}".format(modname))
except Exception as e:
print('Could not load {} {}'.format(modname, e))
여기에 한 가지 방법이 있습니다.
>>> import os
>>> filter(lambda i: type(i) == type(os), [getattr(os, j) for j in dir(os)])
[<module 'UserDict' from '/usr/lib/python2.5/UserDict.pyc'>, <module 'copy_reg' from '/usr/lib/python2.5/copy_reg.pyc'>, <module 'errno' (built-in)>, <module 'posixpath' from '/usr/lib/python2.5/posixpath.pyc'>, <module 'sys' (built-in)>]
확실히 정리하고 개선 할 수 있습니다.
편집 : 약간 더 좋은 버전이 있습니다.
>>> [m[1] for m in filter(lambda a: type(a[1]) == type(os), os.__dict__.items())]
[<module 'copy_reg' from '/usr/lib/python2.5/copy_reg.pyc'>, <module 'UserDict' from '/usr/lib/python2.5/UserDict.pyc'>, <module 'posixpath' from '/usr/lib/python2.5/posixpath.pyc'>, <module 'errno' (built-in)>, <module 'sys' (built-in)>]
>>> [m[0] for m in filter(lambda a: type(a[1]) == type(os), os.__dict__.items())]
['_copy_reg', 'UserDict', 'path', 'errno', 'sys']
참고 :__init__.py
파일 에서 가져 오는 경우 패키지의 하위 디렉터리에 있지 않을 수도있는 모듈도 찾을 수 있으므로 패키지의 "일부"가 의미하는 바에 따라 다릅니다.