python--导入模块名称作为变量(从传递的参数动态加载模块)

python--Import module name as variable (dynamically load module from passed argument)

Python 3.4.2...我一直在尝试从参数动态加载自定义模块。我想加载自定义代码以抓取特定的 HTML 文件。示例:scrape.py -m name_of_module_to_load file_to_scrape.html

我尝试了很多解决方案,包括这个:importing a module when the module name is in a variable

当我使用实际模块名称而不是变量名称时,模块加载正常 args.module

代码:

$ cat scrape.py 
#!/usr/bin/env python3
from urllib.request import urlopen
from bs4 import BeautifulSoup
import argparse
import os, sys
import importlib

parser = argparse.ArgumentParser(description='HTML web scraper')
parser.add_argument('filename', help='File to act on')
parser.add_argument('-m', '--module', metavar='MODULE_NAME', help='File with code specific to the site--must be a defined class named Scrape')
args = parser.parse_args()

if args.module:
#    from get_div_content import Scrape #THIS WORKS#
    sys.path.append(os.getcwd())
    #EDIT--change this:
    #wrong# module_name = importlib.import_module(args.module, package='Scrape')
    #to this:
    module = importlib.import_module(args.module) # correct

try:
    html = open(args.filename, 'r')
except:
    try:
    html = urlopen(args.filename)
    except HTTPError as e:
    print(e)
try:
    soup = BeautifulSoup(html.read())
except:
    print("Error... Sorry... not sure what happened")

#EDIT--change this
#wrong#scraper = Scrape(soup)
#to this:
scraper = module.Scrape(soup) # correct

模块:

$ cat get_div_content.py 
class Scrape:
    def __init__(self, soup):
    content = soup.find('div', {'id':'content'})
    print(content)

命令 运行 和错误:

$ ./scrape.py -m get_div_content.py file.html 
Traceback (most recent call last):
  File "./scrape.py", line 16, in <module>
    module_name = importlib.import_module(args.module, package='Scrape')
  File "/usr/lib/python3.4/importlib/__init__.py", line 109, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 2249, in _gcd_import
  File "<frozen importlib._bootstrap>", line 2199, in _sanity_check
SystemError: Parent module 'Scrape' not loaded, cannot perform relative import

工作命令 -- 无错误:

$ ./scrape.py -m get_div_content file.html
<div id="content">
...
</div>

您不需要包裹。仅使用模块名称

module = importlib.import_module(args.module)

然后你有一个 module 命名空间,其中包含模块中定义的所有内容:

scraper = module.Scrape(soup)

记住,调用时要使用模块名,而不是文件名:

./scrape.py -m get_div_content file.html