如何加载文件夹中的所有模块?

时间:2009-06-29 09:38:16

标签: python python-import

有人能为我提供一个导入整个模块目录的好方法吗? 我有这样的结构:

/Foo
    bar.py
    spam.py
    eggs.py

我尝试通过添加__init__.py并执行from Foo import *将其转换为包,但它没有按照我希望的方式运行。

20 个答案:

答案 0 :(得分:341)

列出当前文件夹中的所有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')]

答案 1 :(得分:123)

__all__变量添加到__init__.py包含:

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

另见http://docs.python.org/tutorial/modules.html

答案 2 :(得分:42)

更新:今天您可能想要使用importlib

通过添加__init__.py使Foo目录成为包。在__init__.py添加:

import bar
import eggs
import spam

既然你想要它是动态的(这可能是也可能不是一个好主意),列出所有包含list dir的py文件并用以下内容导入它们:

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 *不是一个好主意,原因有多种,包括名称冲突以及难以分析代码。

答案 3 :(得分:34)

扩展Mihail的答案,我相信非hackish方式(如,不直接处理文件路径)如下:

  1. __init__.py
  2. 下创建一个空的Foo/文件
  3. 执行
  4. 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'>
    

答案 4 :(得分:20)

Python,包括目录下的所有文件:

对于那些无法让他们工作的新手需要他们的双手。

  1. 创建一个文件夹/ home / el / foo并在/ home / el / foo下创建一个文件main.py。将此代码放在那里:

    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
    

答案 5 :(得分:16)

我自己厌倦了这个问题,所以我写了一个名为automodinit的软件包来修复它。你可以从http://pypi.python.org/pypi/automodinit/获得它。

用法是这样的:

  1. automodinit包添加到setup.py依赖项中。
  2. 替换所有__init__.py文件,如下所示:
  3. __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
    

    因此,“来自M import *”的效果完全匹配“import M”。

    automodinit很高兴从ZIP档案中运行,因此可以保存ZIP。

    尼尔

答案 6 :(得分:7)

我知道我正在更新一篇相当古老的帖子,我尝试使用automodinit,但发现它的设置过程已经被python3破坏了。所以,根据Luca的回答,我想出了一个更简单的答案 - 这可能不适用于.zip - 这个问题,所以我想我应该在这里分享一下:

来自__init__.py的{​​{1}}模块:

yourpackage

并在#!/usr/bin/env python import os, pkgutil __all__ = list(module for _, module, _ in pkgutil.iter_modules([os.path.dirname(__file__)])) 下面的另一个包中:

yourpackage

然后,您将已加载包中的所有模块,如果您编写新模块,它也将自动导入。当然,谨慎使用这种事物,有很大的权力,这是很重要的责任。

答案 7 :(得分:5)

import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)
for imp, module, ispackage in pkgutil.walk_packages(path=__path__, prefix=__name__+'.'):
  __import__(module)

答案 8 :(得分:5)

我也遇到过这个问题,这是我的解决方案:

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

答案 9 :(得分:4)

Anurag Uniyal answer并提出改进建议!

#!/usr/bin/python
# -*- encoding: utf-8 -*-

import os
import glob

all_list = list()
for f in glob.glob(os.path.dirname(__file__)+"/*.py"):
    if os.path.isfile(f) and not os.path.basename(f).startswith('_'):
        all_list.append(os.path.basename(f)[:-3])

__all__ = all_list  

答案 10 :(得分:4)

Anurag的例子有几处更正:

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

答案 11 :(得分:3)

看到您的__init__.py定义__all__modules - packages doc说

  

需要__init__.py个文件才能使Python将目录视为包含包;这样做是为了防止具有通用名称的目录(例如字符串)无意中隐藏稍后在模块搜索路径上发生的有效模块。在最简单的情况下,__init__.py可以只是一个空文件,但它也可以执行包的初始化代码或设置__all__变量,稍后将对此进行描述。

     

...

     

唯一的解决方案是让包作者提供包的显式索引。 import语句使用以下约定:如果包的__init__.py代码定义了名为__all__的列表,则它将被视为遇到包import *时应导入的模块名称列表。在发布新版本的软件包时,由软件包作者决定是否保持此列表的最新状态。如果包装作者没有看到从包装中导入*的用途,他们也可能决定不支持它。例如,文件sounds/effects/__init__.py可以包含以下代码:

     

__all__ = ["echo", "surround", "reverse"]

     

这意味着from sound.effects import *会导入声音包的三个命名子模块。

答案 12 :(得分:3)

这是迄今为止我发现的最佳方式:

from os.path import dirname, join, isdir, abspath, basename
from glob import glob
pwd = dirname(__file__)
for x in glob(join(pwd, '*.py')):
    if not x.startswith('__'):
        __import__(basename(x)[:-3], globals(), locals())

答案 13 :(得分:1)

我为此创建了一个模块,它不依赖于__init__.py(或任何其他辅助文件),只让我输入以下两行:

import importdir
importdir.do("Foo", globals())

随意重复使用或贡献:http://gitlab.com/aurelien-lourot/importdir

答案 14 :(得分:1)

从标准库中查看pkgutil模块。只要目录中有__init__.py文件,它就可以让您完全按照自己的意愿行事。 <{1}}文件可以为空。

答案 15 :(得分:1)

唯一需要添加的是importlib

from importlib import import_module
from pathlib import Path

__all__ = [
    import_module(f".{f.stem}", __package__)
    for f in Path(__file__).parent.glob("*.py")
    if "__" not in f.stem
]
del import_module, Path

答案 16 :(得分:1)

我想补充 Anurag Uniyal 的答案。 你可以让它变得更简单,去掉很多导入。 __init__.py 文件的内容:

    public class NvidiaRoot
    {
        public object categories { get; set; }
        public List<Filter> filters { get; set; }
        public object filterGroups { get; set; }
        public object search { get; set; }
        public string version { get; set; }
        public List<Sort> sort { get; set; }
        public Pagination pagination { get; set; }
        public SearchedProducts searchedProducts { get; set; }
        public Disclaimer disclaimer { get; set; }
    }

    public class FilterValue
    {
        public string dispValue { get; set; }
        public object dispValueDesription { get; set; }
        public object groupType { get; set; }
        public int units { get; set; }
        public bool @checked { get; set; }
        public object imageURL { get; set; }
        public bool isValidate { get; set; }
    }

    public class Filter
    {
        public string displayName { get; set; }
        public string filterField { get; set; }
        public string displayMaxValues { get; set; }
        public string fieldType { get; set; }
        public int? selectedMinRangeVal { get; set; }
        public int? selectedMaxRangeVal { get; set; }
        public int? defaultMinRangeVal { get; set; }
        public int? defaultMaxRangeVal { get; set; }
        public string unitsOfMeasure { get; set; }
        public bool @checked { get; set; }
        public object units { get; set; }
        public List<FilterValue> filterValues { get; set; }
        public string dataType { get; set; }
        public bool showCount { get; set; }
        public int filterDisplayOrder { get; set; }
    }

    public class Sort
    {
        public string displayName { get; set; }
        public string value { get; set; }
        public bool selected { get; set; }
    }

    public class Pagination
    {
        public int page { get; set; }
        public int limit { get; set; }
        public int totalRecords { get; set; }
        public bool featuredProductIncludedInCount { get; set; }
    }

    public class Retailer
    {
        public int productId { get; set; }
        public string productTitle { get; set; }
        public string logoUrl { get; set; }
        public bool isAvailable { get; set; }
        public string salePrice { get; set; }
        public string directPurchaseLink { get; set; }
        public string purchaseLink { get; set; }
        public bool hasOffer { get; set; }
        public object offerText { get; set; }
        public string partnerId { get; set; }
        public string storeId { get; set; }
        public string upc { get; set; }
        public string sku { get; set; }
        public int stock { get; set; }
        public string retailerName { get; set; }
        public int type { get; set; }
    }

    public class ProductInfo
    {
        public string name { get; set; }
        public string value { get; set; }
    }

    public class CompareProductInfo
    {
        public string name { get; set; }
        public string value { get; set; }
    }

    public class FeaturedProduct
    {
        public string displayName { get; set; }
        public int totalCount { get; set; }
        public int productID { get; set; }
        public string imageURL { get; set; }
        public string productTitle { get; set; }
        public string digitialRiverID { get; set; }
        public string productSKU { get; set; }
        public string productUPC { get; set; }
        public string productUPCOriginal { get; set; }
        public string productPrice { get; set; }
        public bool productAvailable { get; set; }
        public object productRating { get; set; }
        public object customerReviewCount { get; set; }
        public bool isFounderEdition { get; set; }
        public bool isFeaturedProduct { get; set; }
        public bool certified { get; set; }
        public string manufacturer { get; set; }
        public string locale { get; set; }
        public bool isFeaturedProdcutFoundInSecondSearch { get; set; }
        public string category { get; set; }
        public string gpu { get; set; }
        public string purchaseOption { get; set; }
        public string prdStatus { get; set; }
        public object minShipDays { get; set; }
        public object maxShipDays { get; set; }
        public object shipInfo { get; set; }
        public bool isOffer { get; set; }
        public string offerText { get; set; }
        public List<Retailer> retailers { get; set; }
        public List<ProductInfo> productInfo { get; set; }
        public List<CompareProductInfo> compareProductInfo { get; set; }
    }

    public class ProductDetail
    {
        public string displayName { get; set; }
        public int totalCount { get; set; }
        public int productID { get; set; }
        public string imageURL { get; set; }
        public string productTitle { get; set; }
        public string digitialRiverID { get; set; }
        public string productSKU { get; set; }
        public string productUPC { get; set; }
        public string productUPCOriginal { get; set; }
        public string productPrice { get; set; }
        public bool productAvailable { get; set; }
        public object productRating { get; set; }
        public object customerReviewCount { get; set; }
        public bool isFounderEdition { get; set; }
        public bool isFeaturedProduct { get; set; }
        public bool certified { get; set; }
        public string manufacturer { get; set; }
        public string locale { get; set; }
        public bool isFeaturedProdcutFoundInSecondSearch { get; set; }
        public string category { get; set; }
        public string gpu { get; set; }
        public string purchaseOption { get; set; }
        public string prdStatus { get; set; }
        public object minShipDays { get; set; }
        public object maxShipDays { get; set; }
        public object shipInfo { get; set; }
        public bool isOffer { get; set; }
        public string offerText { get; set; }
        public List<Retailer> retailers { get; set; }
        public List<ProductInfo> productInfo { get; set; }
        public List<CompareProductInfo> compareProductInfo { get; set; }
    }

    public class SearchedProducts
    {
        public int totalProducts { get; set; }
        public bool featuredProductIncludedInCount { get; set; }
        public bool featuredProductsFlag { get; set; }
        public FeaturedProduct featuredProduct { get; set; }
        public List<ProductDetail> productDetails { get; set; }
        public List<object> suggestedProductDetails { get; set; }
    }

    public class Disclaimer
    {
        public string text { get; set; }
    }




答案 17 :(得分:0)

只需按importlib导入它们,然后将其添加到__all__add操作是可选的),然后递归到__init__.py包中。

/Foo
    bar.py
    spam.py
    eggs.py
    __init__.py

# __init__.py
import os
import importlib
pyfile_extes = ['py', ]
__all__ = [importlib.import_module('.%s' % filename, __package__) for filename in [os.path.splitext(i)[0] for i in os.listdir(os.path.dirname(__file__)) if os.path.splitext(i)[1] in pyfile_extes] if not filename.startswith('__')]
del os, importlib, pyfile_extes

答案 18 :(得分:0)

from . import *不够好时,这是对answer by ted的改进。具体来说,这种方法不需要使用__all__

"""Import all modules that exist in the current directory."""
# Ref https://stackoverflow.com/a/60861023/
from importlib import import_module
from pathlib import Path

for f in Path(__file__).parent.glob("*.py"):
    module_name = f.stem
    if (not module_name.startswith("_")) and (module_name not in globals()):
        import_module(f".{module_name}", __package__)
    del f, module_name
del import_module, Path

请注意,module_name not in globals()旨在避免重新导入模块(如果已导入),因为这可能会导致循环导入。

答案 19 :(得分:-1)

我有一个嵌套的目录结构,即我在包含 python 模块的主目录中有多个目录。

我将以下脚本添加到我的 __init__.py 文件中以导入所有模块

import glob, re, os 

module_parent_directory = "path/to/the/directory/containing/__init__.py/file"

owd = os.getcwd()
if not owd.endswith(module_parent_directory): os.chdir(module_parent_directory)

module_paths = glob.glob("**/*.py", recursive = True)

for module_path in module_paths:
    if not re.match( ".*__init__.py$", module_path):
        import_path = module_path[:-3]
        import_path = import_path.replace("/", ".")
        exec(f"from .{import_path} import *")

os.chdir(owd)

可能不是实现这一目标的最佳方式,但我无法让其他任何事情对我有用。