简体   繁体   English

在python 3中使用pip导入运行时安装的模块

[英]Import runtime installed module using pip in python 3

I want to install and import Python 3 modules at runtime. 我想在运行时安装和导入Python 3模块。

I'm using the following function to install modules at runtime using pip : 我正在使用以下功能在运行时使用pip安装模块:

def installModules(modules):
    for module in modules:
        print("Installing module {}...".format(module))

        subprocess.call([sys.executable, "-m", "pip", "install", "--user", module])

The module is installed successfully, but I'm not able to import it at runtime, after the installation finishes. 该模块已成功安装,但是安装完成后,我无法在运行时导入它。 So if I do: 因此,如果我这样做:

modules = [ "wget", "zipfile2" ]
installModules(module)
import wget

I get a ModuleNotFoundError . 我得到了ModuleNotFoundError If, after that, I start another Python 3 session, I am able to use the modules eg wget , which means that the modules have been installed, but they are not available for this current Python 3 session. 之后,如果我开始另一个Python 3会话,则可以使用模块,例如wget ,这意味着已经安装了模块,但是这些模块不适用于当前的Python 3会话。

Is it possible in Python 3 to install and then import the installed modules in the same Python 3 session ie right after installation? 在Python 3中是否可以在同一Python 3会话中即安装后立即安装并导入已安装的模块?

Thank you! 谢谢!

EDIT: 编辑:

On a fresh Ubuntu 19.04 install inside VirtualBox, after a sudo apt-get install python3-pip , running the following script: 在VirtualBox内的全新Ubuntu 19.04上安装sudo apt-get install python3-pip ,运行以下脚本:

import os, sys
import subprocess


def installModules(modules):
    for module in modules:
        print("Installing module {}...".format(module))

        subprocess.call([sys.executable, "-m", "pip", "install", "--user", module])

def process():
    modulesToInstall = [ "wget", "zipfile2" ]
    installModules(modulesToInstall)

process()

import wget

def main():
    wget.download("http://192.168.2.234/test/configure.py")

if __name__ == "__main__":
    main()

I get: 我得到:

user@user-VirtualBox:~$ python3 script.py
Installing module wget...
Collecting wget
Installing collected packages: wget
Successfully installed wget-3.2
Installing module zipfile2...
Collecting zipfile2
  Using cached https://files.pythonhosted.org/packages/60/ad/d6bc08f235b66c11bbb76df41b973ce93544a907cc0e23c726ea374eee79/zipfile2-0.0.12-py2.py3-none-any.whl
Installing collected packages: zipfile2
Successfully installed zipfile2-0.0.12
Traceback (most recent call last):
  File "script.py", line 17, in <module>
    import wget
ModuleNotFoundError: No module named 'wget'

The Python 3 version is: Python 3版本是:

user@user-VirtualBox:~$ python3 --version
Python 3.7.3

The pip3 version is: pip3版本是:

user@user-VirtualBox:~$ pip3 --version
pip 18.1 from /usr/lib/python3/dist-packages/pip (python 3.7)

Other info: 其他资讯:

user@user-VirtualBox:~$ whereis python3
python3: /usr/bin/python3.7m /usr/bin/python3.7-config /usr/bin/python3.7 /usr/bin/python3 /usr/bin/python3.7m-config /usr/lib/python3.7 /usr/lib/python3.8 /usr/lib/python3 /etc/python3.7 /etc/python3 /usr/local/lib/python3.7 /usr/include/python3.7m /usr/include/python3.7 /usr/share/python3 /usr/share/man/man1/python3.1.gz

Any ideas? 有任何想法吗?

By default, at startup Python adds the user site-packages dir (I'm going to refer to it as USPD ) in the module search paths. 默认情况下, Python在启动时在模块搜索路径中添加用户site-packages dir (我将其称为USPD )。 But this only happens if the directory exists on the file system (disk) . 但这仅在目录存在于文件系统(磁盘)上时才会发生 I didn't find any official documentation to support this statement 1 , so I spent some time debugging and wondering why things seem to be so weird. 我没有找到任何官方文档来支持此声明1 ,因此我花了一些时间进行调试,并想知道为什么事情看起来如此怪异。

The above behavior has a major impact on this particular scenario ( pip install --user ). 上面的行为对这种特殊情况( pip install --user )有重大影响。 Considering the state (at startup) of the Python process that will install modules: 考虑将要安装模块的Python进程的状态(在启动时):

  1. USPD exists: USPD存在:

    • Things are straightforward, everything works OK 事情很简单,一切正常
  2. USPD doesn't exist: USPD不存在:

    • Module installation will create it 模块安装将创建它
    • But, since it's not in the module search paths, all the modules installed there won't be available for (simple) import statements 但是,由于它不在模块搜索路径中,因此那里安装的所有模块将无法用于(简单的) 导入语句

When another Python process is started, it will fall under #1. 当另一个Python进程启动时,它将处于#1以下。

To fix things, USPD should be manually added to module search paths. 为了解决问题,应该将USPD手动添加到模块搜索路径。 Here's how the (beginning of the) script should look like: (的开头)脚本如下所示:

import sys
import os
import subprocess
import site

user_site = site.getusersitepackages()
if user_site not in sys.path:
    sys.path.append(user_site)

# ...

@EDIT0 : @ EDIT0

1 I just came across [Python]: PEP 370 -- Per user site-packages directory - Implementation ( emphasis is mine): 1我刚遇到[Python]:PEP 370-每个用户的site-packages目录-实现重点是我的):

The site module gets a new method adduserpackage() which adds the appropriate directory to the search path. 站点模块获得一个新方法adduserpackage() ,该方法将适当的目录添加到搜索路径。 The directory is not added if it doesn't exist when Python is started . 如果启动Python时该目录不存在,则不会添加该目录

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM