2009-01-28 20 views
69

__all__ का उपयोग किए बिना, पैकेज में सभी मॉड्यूल के नाम सूचीबद्ध करने का एक सीधा तरीका है?क्या पैकेज में पायथन मॉड्यूल के नाम सूचीबद्ध करने का कोई मानक तरीका है?

उदाहरण के लिए

, इस पैकेज दिया:

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

अगर वहाँ इस तरह कुछ करने के लिए एक मानक या निर्मित तरह से मैं सोच रहा हूँ:

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

मैनुअल दृष्टिकोण होगा पैकेज की निर्देशिका को खोजने के लिए मॉड्यूल खोज पथ के माध्यम से पुनरावृत्त करने के लिए। तब कोई उस निर्देशिका में सभी फाइलों को सूचीबद्ध कर सकता है, विशिष्ट नामित पीई/पीईसी/पीओओ फाइलों को फ़िल्टर कर सकता है, एक्सटेंशन को पट्टी कर सकता है, और उस सूची को वापस कर सकता है। लेकिन यह मॉड्यूल आयात तंत्र पहले से ही आंतरिक रूप से कुछ करने के लिए एक उचित मात्रा में काम की तरह लगता है। क्या वह कार्यक्षमता कहीं भी उजागर हुई है?

उत्तर

16

हो सकता है कि यह आपके लिए क्या देख रहे हैं क्या करेंगे?

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

मैं 'और मॉड्यूल! = "__init__.py" को अंतिम' if 'में जोड़ूंगा, क्योंकि __init__.py वास्तव में पैकेज का हिस्सा नहीं है। और .pyo एक और मान्य विस्तार है। इसके अलावा, imp.find_module का उपयोग करना वास्तव में एक अच्छा विचार है; मुझे लगता है कि यह सही जवाब है। – DNS

+3

मैं असहमत हूं - आप सीधे __init__ आयात कर सकते हैं, तो यह विशेष मामला क्यों है? यह निश्चित रूप से नियमों को तोड़ने के लिए पर्याप्त नहीं है। ;-) – cdleary

+5

आपको शायद अपनी हाथ से लिखित सूची के बजाय 'imp.get_suffixes()' का उपयोग करना चाहिए। – itsadok

-1

प्रिंट dir (मॉड्यूल)

+1

सामग्री ओ सूचीबद्ध करता है यही कारण है कि: अजगर 3.6 के साथ और ऊपर काम करता है एक मॉड्यूल जो पहले ही आयात किया जा चुका है। मैं ऐसे पैकेज की सामग्रियों को सूचीबद्ध करने का एक तरीका ढूंढ रहा हूं जिसे अभी तक आयात नहीं किया गया है, जैसे कि 'x import *' से होता है जब __all__ निर्दिष्ट नहीं होता है। एक्स आयात से – DNS

+0

* पहले मॉड्यूल आयात करता है और फिर वर्तमान मॉड्यूल में सबकुछ कॉपी करता है। – Seb

+0

मुझे एहसास हुआ कि 'एक्स आयात * से वास्तव में विंडोज़ पर केस-सेंसिटीविटी के मुद्दों के कारण पैकेज के उप-मॉड्यूल आयात नहीं करता है। मैंने केवल उस उदाहरण के रूप में शामिल किया जो मैं करना चाहता था; भ्रम से बचने के लिए मैंने इसे प्रश्न से बाहर संपादित कर लिया है। – DNS

18
import module 
help(module) 
+1

यद्यपि मदद पाठ के नीचे सूची पैकेज सामग्री की सहायता करता है, प्रश्न यह है कि यह कैसे करें: f (package_name) => ["module1_name", "module2_name"]। मुझे लगता है कि मैं मदद से लौटाई गई स्ट्रिंग को पार्स कर सकता हूं, लेकिन यह निर्देशिका सूचीबद्ध करने से अधिक चौराहे लगता है। – DNS

+0

@DNS: 'मदद()' प्रिंट सामग्री, यह एक स्ट्रिंग वापस नहीं करता है। – Junuxx

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

यह केवल मॉड्यूल के लिए काम करता है, पैकेज नहीं। मेरा मतलब यह देखने के लिए पाइथन के 'लॉगिंग' पैकेज पर आज़माएं। लॉगिंग में दो मॉड्यूल हैं: हैंडलर और कॉन्फ़िगरेशन। आपका कोड 66 आइटमों की एक सूची वापस करेगा, जिसमें उन दो नाम शामिल नहीं हैं। – DNS

155

python2.3 and above का प्रयोग करके आप 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])] 
+14

यह परेशान रूप से अनियंत्रित है, लेकिन ऐसा करने का सबसे सही तरीका लगता है। आशा है कि आपको बुरा लगेगा कि मैंने नोट जोड़ा है। – itsadok

+10

'pkgutil' [python2.3 और वास्तव में] में है (http://docs.python.org/library/pkgutil.html)। साथ ही, जबकि 'pkgutil.iter_modules() 'पुनरावर्ती रूप से काम नहीं करेगा, वहां' pkgutil.walk_packages() 'भी है, जो _will_ recurse है। यद्यपि इस पैकेज के सूचक के लिए धन्यवाद। –

+0

'it.b.testpkg' जैसे पूर्ण आयात के लिए' iter_modules' क्यों काम नहीं करता है? यह मुझे दे रहा है [] ' – Hussain

6

पता नहीं है कि मैं कुछ दिख रहा हूं, या अगर उत्तर सिर्फ बाहर हैं लेकिन;

उपयोगकर्ता 815423426 द्वारा बताए गए अनुसार यह केवल लाइव ऑब्जेक्ट्स के लिए काम करता है और सूचीबद्ध मॉड्यूल केवल मॉड्यूल हैं जो पहले आयात किए गए थे।

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

मैंने आयात किया है = __import __ ('myproj.mymod.mysubmod') m = inspect.getmembers (i, inspect.ismodule) लेकिन आयातित पथ ~/myproj/__ init__.py और m है (mymod, '~/myproj/mymod/__ init__.py') – hithwen

+1

@hithwen टिप्पणियों में प्रश्न न पूछें, खासकर यदि वे नहीं हैं सीधे संबंधित। एक अच्छा समरिटिन होने के नाते: 'आयातित = आयात importlib; importlib.import_module (' myproj.mymod.mysubmod ')'। '__import__' शीर्ष-स्तर मॉड्यूल आयात करता है, [दस्तावेज़ीकरण देखें] (http: // docs .python.org/2/लाइब्रेरी/functions.html #__ import__) – siebz0r

+0

हम्म, यह वादा करता है लेकिन यह मेरे लिए काम नहीं कर रहा है। Wh मैं 'आयात निरीक्षण, mypackage' और फिर' inspect.getmembers (my_package, inspect.ismodule) 'मुझे एक खाली सूची मिलती है, भले ही मेरे पास निश्चित रूप से विभिन्न मॉड्यूल हों। –

0

cdleary के उदाहरण के आधार पर, यहाँ सब submodules के लिए एक पुनरावर्ती संस्करण लिस्टिंग पथ यहां है::

एक पैकेज में लिस्टिंग मॉड्यूल inspect का उपयोग कर वास्तव में आसान लगता है

import imp, os 

def iter_submodules(package): 
    file, pathname, description = imp.find_module('isc_datasources') 
    for dirpath, _, filenames in os.walk(pathname): 
     for filename in filenames: 
      if os.path.splitext(filename)[1] == ".py": 
       yield os.path.join(dirpath, filename) 
1

यह एक पुनरावर्ती संस्करण है कि

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 
संबंधित मुद्दे

 संबंधित मुद्दे