Как динамически загружать модули Python и вызывать метод для каждого из них? - PullRequest
0 голосов
/ 17 апреля 2019

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. Есть ли лучший подход? Почему?

Ответы [ 3 ]

1 голос
/ 17 апреля 2019

Следующее сканирует данный каталог, загружает в него каждый файл .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
0 голосов
/ 17 апреля 2019

Вы захотите использовать модуль inspect для подобных вещей.

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

Даст вам все, что является модулем в вашем пространстве имен.Вы должны быть в состоянии увидеть, как изменить это, чтобы быть более конкретным, если хотите.Уловка запускает eval, чтобы превратить строку имени в ссылку на некоторый объект, который может быть модулем.

0 голосов
/ 17 апреля 2019
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()

Самоанализ, хотя это немного рискованно ... читатель, будьте осторожны

...