【问题标题】:How to dynamically load python modules and call method on each of them?如何动态加载python模块并在每个模块上调用方法?
【发布时间】:2019-09-07 04:54:43
【问题描述】:

这里是 Python 初学者。假设我有三种抓取网站的方法。我们称它们为scrape_site_a、scrape_site_b 和scrape_site_c。我想运行其中的每一个,但我想以这样一种方式定义它们,即我可以动态地调用它们而无需通过名称调用它们。理想情况下,我只想将所有模块加载到一个目录中并在每个模块上调用相同的方法。到目前为止,我的尝试如下:

site_a.py

def scrape():
    # scrape the site

site_b.py

def scrape():
    # scrape the site

site_c.py

def scrape():
    # scrape the site

我有__init__.py 设置,因此我可以执行以下操作:

scrape.py

from sites import *

site_a.scrape()
site_b.scrape()
site_c.scrape()

我想做这样的事情:

for site in sites:
    site.scrape()

我意识到这里有一个我不理解的基本编程概念,我有两个问题:

  1. 有没有办法使用我正在采取的方法来做到这一点?
  2. 有更好的方法吗?为什么?

【问题讨论】:

  • 使用类作为名称板而不是模块。
  • 您正在寻找的是类似于 OSGi 的东西(但它的框架太大,无法一次性解释)。

标签: python design-patterns architecture


【解决方案1】:

下面扫描给定目录,加载其中的每个.py文件,如果存在则调用模块的scrape方法。

from os import listdir
from os.path import join

scraper_dir = "./scrapers"

for scraper_name in listdir(scraper_dir):
    if scraper_name.endswith(".py"):
        with open(join(scraper_dir, scraper_name)) as scraper_file:
            scraper_globals = {}              # this will hold scraper's globals
            scraper_module = exec(scraper_file.read(), scraper_globals)
            if "scrape" in scraper_globals:   # we have a scrape method
                scrape_method = scraper_globals["scrape"]
                callable(scrape_method) and scrape_method()    # call it

【讨论】:

  • 这个答案有点粗略,但确实有效。
【解决方案2】:
from sites import site_a,site_b,site_c
sites = [site_a,site_b,site_c]
for site in sites:
    site.scrape()

我猜可能是你要求的

from sites import *
for item in globals():
    if item.startswith("site_") and hasattr(globals()[item],'scrape'):
       globals()[item].scrape()

这样的内省有点冒险……读者要小心

【讨论】:

  • 这很接近,但我希望它是动态的。理想情况下,我想将所有模块加载到一个目录中,并在每个模块中调用一个方法(每个方法都具有相同的名称)。我已经更新了我的问题,以便更清楚地了解这一点
【解决方案3】:

你会想要使用 inspect 模块来处理这样的事情。

import inspect
modules = [mod for mod in globals() if inspect.ismodule(eval(mod))]

将为您提供命名空间中的所有模块。如果需要,您应该能够看到如何将其修改为更具体。诀窍是运行 eval 以将名称字符串转换为对某个对象的引用,该对象可能是一个模块。

【讨论】:

    猜你喜欢
    • 2013-11-10
    • 2010-10-20
    • 2010-10-31
    • 1970-01-01
    • 2019-05-18
    • 2011-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多