سؤال

هل هناك طريقة مباشرة للعثور على جميع الوحدات التي تشكل جزءًا من حزمة بايثون؟لقد وجدت هذه المناقشة القديمة, ، وهو ليس قاطعًا حقًا، ولكني أرغب في الحصول على إجابة محددة قبل طرح الحل الخاص بي استنادًا إلى 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 ملف، لذلك يعتمد على ما تقصد به "جزء من" حزمة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top