পাইথন প্যাকেজের অংশ এমন সমস্ত মডিউল খুঁজে পাওয়ার কোনও সরল উপায় আছে? আমি এই পুরানো আলোচনাটি পেয়েছি , যা সত্যই চূড়ান্ত নয়, তবে os.listdir () এর ভিত্তিতে নিজের সমাধানটি সমাধান করার আগে আমি একটি নির্দিষ্ট উত্তর দিতে পছন্দ করব।
পাইথন প্যাকেজের অংশ এমন সমস্ত মডিউল খুঁজে পাওয়ার কোনও সরল উপায় আছে? আমি এই পুরানো আলোচনাটি পেয়েছি , যা সত্যই চূড়ান্ত নয়, তবে 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
importer
ফিরে আসে pkgutil.iter_modules
? এটিকে সম্ভবত "হ্যাকিশ" ব্যবহার না করে কোনও মডিউল আমদানি করতে আমি কি এটি ব্যবহার করতে পারি __import__(modname, fromlist="dummy")
?
m = importer.find_module(modname).load_module(modname)
m
m.myfunc()
_path_
) কেবল একটি আন্ডারস্কোর ব্যবহার করছেন । মোট চারটি (অর্থাত্ __path__
) জন্য দু'দিকে দুটি হওয়া উচিত ।
এই কাজের জন্য সঠিক সরঞ্জামটি হল pkgutil.walk_packages।
আপনার সিস্টেমে সমস্ত মডিউল তালিকাভুক্ত করতে:
import pkgutil
for importer, modname, ispkg in pkgutil.walk_packages(path=None, onerror=lambda x: None):
print(modname)
সচেতন থাকুন যে ওয়াক_প্যাকেজগুলি সমস্ত উপ-প্যাকেজগুলি আমদানি করে, তবে সাবমডিউলগুলি নয়।
আপনি যদি একটি নির্দিষ্ট প্যাকেজের সমস্ত সাবমোডিয়ুল তালিকাভুক্ত করতে চান তবে আপনি এই জাতীয় কিছু ব্যবহার করতে পারেন:
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 কেবলমাত্র এক-স্তর গভীর মডিউলগুলি তালিকাভুক্ত করে। ওয়াক_প্যাকেজগুলি সমস্ত সাবমডিউল পায়। স্কিপির ক্ষেত্রে, উদাহরণস্বরূপ, ওয়াক_প্যাকেজগুলি ফেরত দেয়
scipy.stats.stats
যদিও iter_modules কেবল ফেরত দেয়
scipy.stats
Pkgutil ( http://docs.python.org/library/pkgutil.html ) - তে থাকা ডকুমেন্টেশনগুলি /usr/lib/python2.6/pkgutil.py এ সংজ্ঞায়িত সমস্ত আকর্ষণীয় ফাংশন তালিকাভুক্ত করে না।
সম্ভবত এর অর্থ এই যে ফাংশনগুলি "পাবলিক" ইন্টারফেসের অংশ নয় এবং পরিবর্তিত হতে পারে।
তবে পাইথন কমপক্ষে ২.6 হিসাবে (এবং সম্ভবত পূর্ববর্তী সংস্করণগুলি?) পিকগটিল ওয়াক_প্যাকেজ পদ্ধতিতে আসে যা উপলভ্য সমস্ত মডিউলগুলির মধ্যে পুনরাবৃত্তি করে।
walk_packages
ডকুমেন্টেশনে এখন রয়েছে: docs.python.org/library/pkgutil.html#pkgutil.walk_packages
_
আগে ও পরে দুটি আন্ডারস্কোর থাকতে হবে path
- এর পরিবর্তে ব্যবহার করুনpackage.__path__
package._path_
। কোডটি পুনরায় টাইপ করার চেয়ে কাটা এবং পেস্ট করার চেষ্টা করা আরও সহজ হতে পারে।
package
কোনও প্যাকেজের দিকে নির্দেশ করছে, কোনও মডিউল নয়। মডিউলগুলি ফাইল যেখানে প্যাকেজগুলি ডিরেক্টরি। সমস্ত প্যাকেজটির __path__
বৈশিষ্ট্য রয়েছে (... যদি না কারও কারও কারণে অ্যাট্রিবিউটটি মুছে ফেলা হয়।)
এটি আমার পক্ষে কাজ করে:
import types
for key, obj in nltk.__dict__.iteritems():
if type(obj) is types.ModuleType:
print key
আমি আমার প্যাকেজে লাইভ সম্পাদনা করছি এমন সমস্ত সাবমোডিউলগুলি পুনরায় লোড করার একটি উপায় অনুসন্ধান করছিলাম। এটি উপরের উত্তর / মন্তব্যের সংমিশ্রণ, তাই আমি মন্তব্য করার চেয়ে উত্তর হিসাবে এখানে পোস্ট করার সিদ্ধান্ত নিয়েছি।
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
ফাইলটিতে টানতে থাকে, সুতরাং এটি কোনও প্যাকেজের "অংশ" বলতে কী বোঝায় তার উপর নির্ভর করে।