একটি প্যাকেজে পাইথন মডিউলগুলির নাম তালিকাভুক্ত করার জন্য কি কোনও স্ট্যান্ডার্ড উপায় আছে?


102

ব্যবহার না করে কোনও প্যাকেজে সমস্ত মডিউলের নাম তালিকাভুক্ত করার সোজা উপায় আছে __all__?

উদাহরণস্বরূপ, এই প্যাকেজটি দেওয়া:

/testpkg
/testpkg/__init__.py
/testpkg/modulea.py
/testpkg/moduleb.py

আমি ভাবছি যে এরকম কিছু করার কোনও মানক বা অন্তর্নির্মিত উপায় আছে কিনা:

>>> package_contents("testpkg")
['modulea', 'moduleb']

ম্যানুয়াল পদ্ধতির প্যাকেজটির ডিরেক্টরি সন্ধানের জন্য মডিউল অনুসন্ধানের পথগুলি দিয়ে পুনরাবৃত্তি করা হবে। এরপরে কেউ সেই ডিরেক্টরিতে থাকা সমস্ত ফাইল তালিকাভুক্ত করতে পারে, অনন্য-নামযুক্ত পাই / পাইক / পাইও ফাইলগুলি ফিল্টার করতে পারে, এক্সটেনশানগুলি সজ্জিত করতে পারে এবং সেই তালিকাটি ফিরে আসতে পারে। তবে এটি মডিউল আমদানি প্রক্রিয়া ইতিমধ্যে অভ্যন্তরীণভাবে করছে এমন কোনও কিছুর জন্য মোটামুটি কাজের মতো মনে হচ্ছে। যে কার্যকারিতা কোথাও উন্মুক্ত?

উত্তর:


24

সম্ভবত এটি আপনি যা খুঁজছেন তা করবে?

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)])

4
আমি যোগ হবে 'এবং মডিউল! = " Init .py"' চূড়ান্ত 'যদি' থেকে, যেহেতু Init .py সত্যিই প্যাকেজের অংশ নয়। এবং .pyo হল অন্য বৈধ এক্সটেনশন। এ ছাড়া, imp.find_module ব্যবহার করা সত্যিই ভাল ধারণা; আমি মনে করি এটিই সঠিক উত্তর।
DNS

4
আমি একমত নই - আপনি সরাসরি init আমদানি করতে পারেন , তবে কেন এটি বিশেষ ক্ষেত্রে? এটি নিশ্চিত যে নিয়মগুলি ভাঙ্গার পক্ষে যথেষ্ট বিশেষ নয়। ;-)
সিডলারি

6
imp.get_suffixes()আপনার নিজের হাতে লিখিত তালিকার পরিবর্তে সম্ভবত ব্যবহার করা উচিত ।
itadok

4
এছাড়াও, নোট করুন যে এটি সাবxml.sax
প্যাকেজগুলিতে

4
এটি সত্যিই খারাপ উপায়। আপনি ফাইলের নাম এক্সটেনশন থেকে মডিউলটি নির্ভরযোগ্যভাবে বলতে পারবেন না।
wim

193

পাইথন 2.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])]

16
এটি বিরক্তিকরভাবে অননুমোদিত, তবে এটি করার সবচেয়ে সঠিক উপায় বলে মনে হচ্ছে। আশা করি আপনি আপত্তি করবেন না আমি নোটটি যুক্ত করেছি।
itadok

13
pkgutilরয়েছে python2.3 এবং আপ আসলে । এছাড়াও, যখন pkgutil.iter_modules()যাও recursively কাজ করবে না, একটা হল pkgutil.walk_packages()পাশাপাশি যা হবে recurse। যদিও এই প্যাকেজটির পয়েন্টারটির জন্য ধন্যবাদ।
সন্দীপ ভট্টাচার্য

iter_modulesপরম আমদানির মতো কেন কাজ করে না a.b.testpkg? এটি আমাকে দিচ্ছে[]
হুসেন

আমি আপনার সম্পাদনা উপেক্ষা করেছি :( দুঃখিত, দ্বিতীয় স্নিপেট অনুসরণ করার পরে এটি কাজ করে
হুসেন

4
আমি নিশ্চিত হতে পারি না যে pkgutil.walk_packages()পুনরাবৃত্তি হয়, এটি আমাকে একই আউটপুট দেয় pkgutil.iter_modules(), তাই আমি মনে করি উত্তরটি অসম্পূর্ণ।
rwst

29
import module
help(module)

4
যদিও সহায়তা সহায়তা পাঠ্যের নীচে প্যাকেজ সামগ্রীগুলি তালিকাভুক্ত করে, প্রশ্নটি কীভাবে এটি করা যায় তার পংক্তিতে আরও রয়েছে: চ (প্যাকেজ_নাম) => ["মডিউল 1_নাম", "মডিউল 2_নাম"]। আমি মনে করি সাহায্যের সাহায্যে ফিরে আসা স্ট্রিংটিকে পার্স করতে পারব, তবে ডিরেক্টরিটি তালিকাভুক্ত করার চেয়ে চারিদিক মনে হচ্ছে।
ডিএনএস

4
@ ডিএনএস: স্টাফগুলি help()মুদ্রণ করে, এটি কোনও স্ট্রিং দেয় না।
জুনউক্সেক্স

আমি সম্মত হলাম এটি একটি চক্রাকার রাস্তা তবে এটি কীভাবে help()কাজ করে তা দেখতে আমাকে খরগোশের ছিদ্রটি নামিয়ে দিয়েছিল । যাই হোক, বিল্ট-ইন pydocমডিউল থুতু সাহায্য করতে পারেন স্ট্রিংটি help()paginates: import pydoc; pydoc.render_doc('mypackage')
sraboy

9

আমি কিছু উপেক্ষা করছি কিনা জানি না, বা উত্তরগুলি কেবল সেকেলে থাকলেও;

যেমন ব্যবহারকারী 815423426 বলেছে এটি কেবল লাইভ অবজেক্টের জন্য কাজ করে এবং তালিকাভুক্ত মডিউলগুলি কেবলমাত্র মডিউল যা আগে আমদানি করা হয়েছিল।

কোনও প্যাকেজে তালিকাভুক্ত মডিউলগুলি পরিদর্শন ব্যবহার করে সত্যই সহজ বলে মনে হচ্ছে :

>>> import inspect, testpkg
>>> inspect.getmembers(testpkg, inspect.ismodule)
['modulea', 'moduleb']

আমি আমদানি করা = আমদানি __ ('myproj.mymod.mysubmod') m = inspect.getmebers (i, inspect.ismodule) রেখেছি তবে আমদানি করা পথটি ~ / myproj / __ init .py এবং m (মায়োমড, 'with সহ একটি তালিকা / মাইপ্রোজ / মায়োমড / inইনিট__.পি ')
হিথউইন

4
@ হিটওয়েন মন্তব্যগুলিতে প্রশ্ন জিজ্ঞাসা করবেন না, বিশেষত যদি তারা সরাসরি সম্পর্কিত না হয়। ভাল সামারিটান হওয়া: ব্যবহার করুন imported = import importlib; importlib.import_module('myproj.mymod.mysubmod')__import__শীর্ষ স্তরের মডিউল আমদানি করে, ডকুমেন্টেশন দেখুন
siebz0r

হুম, এটি প্রতিশ্রুতিশীল তবে এটি আমার পক্ষে কাজ করছে না। আমি যখন করি import inspect, mypackageএবং তারপরে inspect.getmembers(my_package, inspect.ismodule)আমি একটি খালি তালিকা পাই, যদিও আমার এটিতে অবশ্যই বিভিন্ন মডিউল রয়েছে।
অ্যামিলিও ওয়াজকেজ-রেইনা

4
প্রকৃতপক্ষে, এটি কেবলমাত্র আমি import my_package.fooএবং শুধু নয় import mypackage, যদি এরপরে ফিরে আসে তবে এটি কেবল কাজ করে বলে মনে হচ্ছে foo। তবে এটি উদ্দেশ্যকে পরাস্ত করে
আমেলিও ওয়াজকেজ-রেইনা

4
@ user815423426 আপনি একেবারে ঠিক বলেছেন ;-) মনে হচ্ছে আমি কোনও কিছু উপেক্ষা করছি।
siebz0r

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

4
@ মোমকুট ডকস.পিথন.আর.৩ / ৩ / লিবারি /os.html#os.scandir দেখুন যা আপনাকে কোনও কনটেক্সট ম্যানেজার হিসাবে ব্যবহার করার পরামর্শ দেয় যাতে কোনও হোল্ডclose রিসোর্স প্রকাশিত হয় না তা নিশ্চিত করার জন্য আপনাকে এটি সম্পন্ন করার সময় ডাকা হয়।
টাকসওয়েল

reএটি পরিবর্তে এটি প্রতিটি প্যাকেজ তালিকাবদ্ধ করে কাজ করে না তবে re.তাদের সকলকে যুক্ত করে
তুষার্তজ

1

সিডেলারির উদাহরণের ভিত্তিতে, এখানে সমস্ত সাবমোডিয়ুলের জন্য পুনরাবৃত্ত সংস্করণ তালিকা পাথ দেওয়া হয়েছে:

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

আপনি যদি পাইথন কোডের বাইরে আপনার প্যাকেজ সম্পর্কে কোনও তথ্য দেখতে চান (কমান্ড প্রম্পট থেকে) আপনি এর জন্য পাইডোক ব্যবহার করতে পারেন।

# 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>

আপনি পাইডোকের মতো একই ব্যবহার করতে পারবেন তবে সাহায্যকারীর সাহায্যে দোভাষীর ভিতরে

>>> import <my package>
>>> help(<my package>)

-3

মুদ্রণ দির (মডিউল)


4
এটি ইতিমধ্যে আমদানি করা মডিউলটির সামগ্রীগুলি তালিকাভুক্ত করে। আমি এমন প্যাকেজের সামগ্রীগুলি তালিকাভুক্ত করার জন্য একটি উপায় খুঁজছি যা এখনও আমদানি করা হয়নি, যেমন 'এক্স ইম্পোর্ট * থেকে' সমস্ত সুনির্দিষ্ট না করা হয়।
ডিএনএস

এক্স ইম্পোর্ট * থেকে প্রথমে মডিউল আমদানি করে এবং তারপরে বর্তমান মডিউলে সমস্ত কিছু অনুলিপি করে।
15-29

আমি বুঝতে পেরেছি যে 'উইন্ডোজ থেকে এক্স ইম্পোর্ট *' আসলে প্যাকেজের সাব-মডিউলগুলি আমদানি করে না, কারণ উইন্ডোজে কেস-সংবেদনশীলতার সমস্যা রয়েছে। আমি কেবল এটিই অন্তর্ভুক্ত করেছি যা আমি করতে চেয়েছিলাম তার উদাহরণ হিসাবে; বিভ্রান্তি এড়াতে আমি প্রশ্নটি সম্পাদনা করেছি।
ডিএনএস

এটি ইতিমধ্যে আমদানি করা সামগ্রীর সমস্ত বৈশিষ্ট্য তালিকাভুক্ত করে, কেবলমাত্র সাব-মডিউলগুলির তালিকা নয়। সুতরাং এটি প্রশ্নের উত্তর দেয় না।
বাইনোজ করুন

-3
def package_contents(package_name):
  package = __import__(package_name)
  return [module_name for module_name in dir(package) if not module_name.startswith("__")]

এটি কেবল প্যাকেজ নয়, মডিউলগুলির জন্য কাজ করে। loggingআমি কী বলতে চাইছি তা দেখতে পাইথনের প্যাকেজে এটি ব্যবহার করে দেখুন। লগিংয়ে দুটি মডিউল থাকে: হ্যান্ডলার এবং কনফিগার। আপনার কোডটি items 66 টি আইটেমের একটি তালিকা ফিরিয়ে দেবে, যার মধ্যে দুটি নাম অন্তর্ভুক্ত নেই।
ডিএনএস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.