Как загрузить все модули в папке? - PullRequest
223 голосов
/ 29 июня 2009

Может ли кто-нибудь предоставить мне хороший способ импорта целого каталога модулей?
У меня есть такая структура:

/Foo
    bar.py
    spam.py
    eggs.py

Я попытался просто преобразовать его в пакет, добавив __init__.py и выполнив from Foo import *, но это не сработало так, как я надеялся.

Ответы [ 16 ]

344 голосов
/ 29 июня 2009

Вывести список всех файлов Python (.py) в текущей папке и поместить их как переменную __all__ в __init__.py

from os.path import dirname, basename, isfile, join
import glob
modules = glob.glob(join(dirname(__file__), "*.py"))
__all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]
123 голосов
/ 29 июня 2009

Добавьте переменную __all__ к __init__.py, содержащую:

__all__ = ["bar", "spam", "eggs"]

См. Также http://docs.python.org/tutorial/modules.html

43 голосов
/ 29 июня 2009

Обновление: сегодня вы, вероятно, хотите использовать importlib.

Сделать каталог Foo пакетом, добавив __init__.py. В этом __init__.py добавить:

import bar
import eggs
import spam

Поскольку вы хотите, чтобы он был динамическим (что может или не может быть хорошей идеей), перечислите все py-файлы со списком dir и импортируйте их примерно так:

import os
for module in os.listdir(os.path.dirname(__file__)):
    if module == '__init__.py' or module[-3:] != '.py':
        continue
    __import__(module[:-3], locals(), globals())
del module

Затем из вашего кода сделайте следующее:

import Foo

Теперь вы можете получить доступ к модулям с помощью

Foo.bar
Foo.eggs
Foo.spam

и т.д.. из Foo import * не очень хорошая идея по нескольким причинам, включая конфликт имен и усложнение анализа кода.

34 голосов
/ 19 декабря 2011

Продолжая ответ Михаила, я считаю, что нехакерский способ (например, не обрабатывать пути к файлам напрямую) заключается в следующем:

  1. создать пустой __init__.py файл в Foo/
  2. Выполнить
import pkgutil
import sys


def load_all_modules_from_dir(dirname):
    for importer, package_name, _ in pkgutil.iter_modules([dirname]):
        full_package_name = '%s.%s' % (dirname, package_name)
        if full_package_name not in sys.modules:
            module = importer.find_module(package_name
                        ).load_module(full_package_name)
            print module


load_all_modules_from_dir('Foo')

Вы получите:

<module 'Foo.bar' from '/home/.../Foo/bar.pyc'>
<module 'Foo.spam' from '/home/.../Foo/spam.pyc'>
20 голосов
/ 24 декабря 2013

Python, включите все файлы в каталоге:

Для новичков, которые просто не могут заставить его работать, которым нужны руки.

  1. Создайте папку / home / el / foo и создайте файл main.py в / home / el / foo Вставьте этот код туда:

    from hellokitty import *
    spam.spamfunc()
    ham.hamfunc()
    
  2. Сделать каталог /home/el/foo/hellokitty

  3. Создайте файл __init__.py в /home/el/foo/hellokitty и вставьте туда этот код:

    __all__ = ["spam", "ham"]
    
  4. Создайте два файла Python: spam.py и ham.py в /home/el/foo/hellokitty

  5. Определить функцию внутри spam.py:

    def spamfunc():
      print "Spammity spam"
    
  6. Определить функцию внутри ham.py:

    def hamfunc():
      print "Upgrade from baloney"
    
  7. Запустите его:

    el@apollo:/home/el/foo$ python main.py 
    spammity spam
    Upgrade from baloney
    
16 голосов
/ 05 марта 2012

Я устал от этой проблемы сам, поэтому я написал пакет под названием automodinit, чтобы исправить ее. Вы можете получить его от http://pypi.python.org/pypi/automodinit/.

Использование выглядит так:

  1. Включите пакет automodinit в ваши setup.py зависимости.
  2. Заменить все файлы __init__.py следующим образом:
__all__ = ["I will get rewritten"]
# Don't modify the line above, or this line!
import automodinit
automodinit.automodinit(__name__, __file__, globals())
del automodinit
# Anything else you want can go after here, it won't get modified.

Вот и все! Отныне импорт модуля установит __all__ в список .py [co] файлов в модуле, а также будет импортировать каждый из этих файлов, как будто вы набрали:

for x in __all__: import x

Следовательно, эффект «from M import *» в точности совпадает с «import M».

automodinit отлично работает изнутри ZIP-архивов и поэтому безопасен для ZIP.

Найл

8 голосов
/ 26 марта 2016

Я знаю, что обновляю довольно старый пост, и я попытался использовать automodinit, но обнаружил, что процесс установки нарушен для python3. Итак, основываясь на ответе Луки, я пришел к более простому ответу - который может не работать с .zip - на этот вопрос, поэтому я решил поделиться им здесь:

в модуле __init__.py от yourpackage:

#!/usr/bin/env python
import os, pkgutil
__all__ = list(module for _, module, _ in pkgutil.iter_modules([os.path.dirname(__file__)]))

и в другом пакете ниже yourpackage:

from yourpackage import *

Тогда у вас будут загружены все модули, которые находятся внутри пакета, и если вы напишите новый модуль, он также будет автоматически импортирован. Конечно, с осторожностью относитесь к подобным вещам, с великими способностями возникают большие обязанности.

5 голосов
/ 07 июня 2016
import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)
for imp, module, ispackage in pkgutil.walk_packages(path=__path__, prefix=__name__+'.'):
  __import__(module)
5 голосов
/ 31 июля 2012

Я также столкнулся с этой проблемой, и это было мое решение:

import os

def loadImports(path):
    files = os.listdir(path)
    imps = []

    for i in range(len(files)):
        name = files[i].split('.')
        if len(name) > 1:
            if name[1] == 'py' and name[0] != '__init__':
               name = name[0]
               imps.append(name)

    file = open(path+'__init__.py','w')

    toWrite = '__all__ = '+str(imps)

    file.write(toWrite)
    file.close()

Эта функция создает файл (в предоставленной папке) с именем __init__.py, который содержит переменную __all__, которая содержит каждый модуль в папке.

Например, у меня есть папка с именем Test который содержит:

Foo.py
Bar.py

Итак, в скрипте, в который я хочу импортировать модули, я напишу:

loadImports('Test/')
from Test import *

Это импортирует все из Test, а файл __init__.py в Test теперь будет содержать:

__all__ = ['Foo','Bar']
4 голосов
/ 19 ноября 2014

Пример Анурага с парой исправлений:

import os, glob

modules = glob.glob(os.path.join(os.path.dirname(__file__), "*.py"))
__all__ = [os.path.basename(f)[:-3] for f in modules if not f.endswith("__init__.py")]
...