修改Python / PIP以在导入失败时自动安装模块

时间:2015-03-31 08:53:52

标签: python automation pip

有没有办法修改python / pip,每当导入在运行时失败时,它会尝试从pip安装模块(同名)然后导入模块?< / p>

我会说这是一个更好的默认值,而不仅仅是抛出一个错误。如果在从pip加载模块后发生任何问题,那么它也会抛出一个错误,类似于我注意到我无法导入某些内容时,请尝试pip install然后转到同样的错误消息

我知道我们可以使用requirements.txt来捆绑一个包,但我是从“客户端”(运行脚本的人)而不是“提供者”(提供脚本的人)角度谈论的;也就是说,作为客户,我希望能够导入任何脚本并自动解决依赖关系。

我知道这可能会带来麻烦,但每当我看到一个ImportError时,我只会尝试pip install模块。只有在pip安装后模块无法正常工作时“我才会问更多问题”。

我想到了像python进程“内置”的这个片段:

def getDirectoryOfInterpreter(p):
    return "someway to return the directory"

try:
    import somemodule
except ImportError:
    os.system(getDirectoryOfInterpreter('THIS_INTERPRETER_BINARY') + ' pip install ' + "MODULE_NAME")
    import somemodule

2 个答案:

答案 0 :(得分:12)

使用virtualenv时,您可以使用pipimport执行此操作。如果你有适当的权限来编写必要的目录(至少site-packages,它可能适用于系统python,但你的导入可能有一些命令,pip将尝试将某些地方放在PATH中。因为最好总是使用virtualenvs来进行自己的开发,所以我从没尝试将pipimport用于系统python。

你需要手动将pipimport导入你的virtualenv:

virtualenv venv
source venv/bin/activate
pip install pipimport

然后创建一个您在任何模块中首先导入的文件autopipimport.py

# import and install pipimport
import pipimport
pipimport.install()

现在,您可以执行任何其他.py文件:

import autopipimport
import some.package.installable.by.pip

我曾尝试过(好奇心自动)将两条与pipimport相关的行添加到venv/lib/python2.7/site.py以自动加载&#34;,但那是在链的早期并且不起作用。< / p>

pipimport只会尝试使用pip一次安装特定模块,并存储有关.pipimport-ignore文件中已尝试内容的信息(应在venv下,除非那是不可写的。)

答案 1 :(得分:0)

这是我为了自己的好奇而做的事情。

是的,这会使用非首选函数通过任意用户输入在后台不安全地调用shell。请不要将此代码用于生产。

import os

Libraries_Installed = False

def Pip_Install(library):
    """Locate pip.exe on system and install library.
    Be sure to sanitize input to prevent RCE."""
    global Lib_Installed

    if os.path.isfile('C:\\Python27\\Scripts\\pip.exe'):
        print '[!] c:\Python27\Scripts\pip.exe => pip'
        stream = os.popen('C:\Python27\Scripts\pip.exe install %s' % library)
        Result = stream.read()

        if 'Successfully installed' in str(Result):
            print '\n\n[+] Successfully installed %s' % library
            Lib_Installed = True

        elif 'FAIL' in str(Result).upper() or 'FAILED' in str(Result).upper() \
        or 'FAILURE' in str(Result).upper():
            print '[!] Unable to install %d' % library
            print '[!] Please manually run the pip installer'
            print '[!] try: C:\Python27\Scripts\pip.exe install %s' % library

    elif os.path.isfile('D:\\Python27\\Scripts\\pip.exe'):
        stream = os.popen('D:\Python27\Scripts\pip.exe install %s' % library)
        Result = stream.read()

        if 'Successfully installed' in str(Result):
            print '\n\n[+] Successfully installed %s' % library
            Lib_Installed = True

        elif 'FAIL' in str(Result).upper() or 'FAILED' in str(Result).upper() \
        or 'FAILURE' in str(Result).upper():
            print '[!] Unable to install %d' % library
            print '[!] Please manually run the pip installer'
            print '[!] try: C:\Python27\Scripts\pip.exe install %s' % library

# Python library that may need to be installed
try:
    import Tkinter
    import tkFileDialog
except:
    print '[!] Error importing Tkinter ... Trying pip installer'
    Pip_Install('tkinter')

if Lib_Installed == True:
    print '\n[!] The following Python libraries were installed automatically:'
    for library in Libs:
        print str(library)
    Q = raw_input('''\n[!] Please exit the program and run a new instance.
[!] Enter [Y] to continue anyways''')
    if Q.upper()[0] == 'Y':
        pass
    else:
        exit()