قائمة بجميع الوحدات التي تشكل جزءًا من حزمة بايثون؟
-
19-09-2019 - |
سؤال
هل هناك طريقة مباشرة للعثور على جميع الوحدات التي تشكل جزءًا من حزمة بايثون؟لقد وجدت هذه المناقشة القديمة, ، وهو ليس قاطعًا حقًا، ولكني أرغب في الحصول على إجابة محددة قبل طرح الحل الخاص بي استنادًا إلى os.listdir().
المحلول
نعم، تريد شيئا بناء على pkgutil
أو ما شابه ذلك - بهذه الطريقة يمكنك التعامل مع جميع الحزم على حد سواء بغض النظر عما إذا كانت في البيض أو الكود البريدية أو نحو ذلك (لن يساعد 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
نصائح أخرى
الأداة المناسبة لهذه المهمة هي 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 التي تسير بشكل متكرر من خلال جميع الوحدات النمطية المتاحة.
هذا يعمل بالنسبة لي:
import types
for key, obj in nltk.__dict__.iteritems():
if type(obj) is types.ModuleType:
print key
إليك طريقة واحدة، خارج الجزء العلوي من رأسي:
>>> 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
ملف، لذلك يعتمد على ما تقصد به "جزء من" حزمة.