【问题标题】:have python script check for missing modules and install if missing让 python 脚本检查丢失的模块并在丢失时安装
【发布时间】:2018-03-05 18:24:05
【问题描述】:

我正在寻求使我编写的脚本更便携。

我的脚本中使用的一些工具需要安装某些模块。我已经能够让脚本自行安装模块,但希望有一种机制来检查它们是否已经安装,并且只有在缺失时才尝试安装。

我确信这是可能的,但我似乎找不到解决方案。

【问题讨论】:

标签: python


【解决方案1】:

你可以试试这个:

import pip
def install(package):
    pip.main(['install', package])

try:
    import your_module
except ImportError:
    print 'Module not installed'
    install('your_module')

【讨论】:

    【解决方案2】:

    解决这个问题的标准方法是把你的脚本变成一个模块,declare its dependencies in the setup.py of the module.

    from setuptools import setup
    
    setup(name='foo',
      ...
      install_requires=['dependency', 'other', ...])
    

    支持性较弱的约定是在requirements.txt 中保留一个列表,以便您可以

    pip install -r requirements.txt
    

    让你自己的脚本来做这些家务通常没有用也没有必要;现有的打包基础设施已经提供了你需要的东西,并且是操作和管理包依赖关系的自然点。

    从历史上看,随着不同的封装机制在 Python 生态系统中争夺主导地位,曾出现过一些动荡,但现在看来,setuptoolspip 已基本确定。

    【讨论】:

    【解决方案3】:

    通常,代表运行您的脚本的人下载和安装东西并不好。正如 Triplee 的回答所提到的,使用 requirements.txt 和适当的 setup.py 是一种标准且更好的做法。

    无论如何,以下是在脚本中获得所需行为的技巧。

    import pip
    import importlib
    modules = ['requests', 'fake_module_name_that_does_not_exist']
    for modname in modules:
        try:
            # try to import the module normally and put it in globals
            globals()[modname] = importlib.import_module(modname)
        except ImportError as e:
            result = pip.main(['install', modname])
            if result != 0: # if pip could not install it reraise the error
                raise
            else:
                # if the install was sucessful, put modname in globals
                globals()[modname] = importlib.import_module(modname)
    

    如果你要执行这个例子,你会得到如下输出

    Collecting requests
      Using cached requests-2.18.4-py2.py3-none-any.whl
    Requirement already satisfied: idna<2.7,>=2.5 in c:\users\spenceryoung\envs\test_venv\lib\site-packages (from requests)
    Requirement already satisfied: urllib3<1.23,>=1.21.1 in c:\users\spenceryoung\envs\test_venv\lib\site-packages (from requests)
    Requirement already satisfied: chardet<3.1.0,>=3.0.2 in c:\users\spenceryoung\envs\test_venv\lib\site-packages (from requests)
    Requirement already satisfied: certifi>=2017.4.17 in c:\users\spenceryoung\envs\test_venv\lib\site-packages (from requests)
    Installing collected packages: requests
    Successfully installed requests-2.18.4
    Collecting fake_module_name_that_does_not_exist
      Could not find a version that satisfies the requirement fake_module_name_that_does_not_exist (from versions: )
    No matching distribution found for fake_module_name_that_does_not_exist
    Traceback (most recent call last):
      File "<stdin>", line 3, in <module>
      File "C:\Users\spenceryoung\AppData\Local\Programs\Python\Python36-32\lib\importlib\__init__.py", line 126, in import_module
        return _bootstrap._gcd_import(name[level:], package, level)
      File "<frozen importlib._bootstrap>", line 994, in _gcd_import
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
    ModuleNotFoundError: No module named 'fake_module_name_that_does_not_exist'
    

    【讨论】:

    • 感谢您提供适合我尝试完成的选项(即使它不是最佳实践)。我现在知道该往哪个方向看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-04
    • 2011-04-23
    • 2012-06-01
    • 2011-09-10
    • 1970-01-01
    • 2020-09-26
    • 2020-12-27
    相关资源
    最近更新 更多