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

标签 python python-3.x pip subprocess

我要安装和导入Python 3运行时的模块。

我正在使用以下函数在运行时使用 pip 安装模块:

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

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

该模块已成功安装,但安装完成后我无法在运行时导入它。所以如果我这样做:
modules = [ "wget", "zipfile2" ]
installModules(module)
import wget

我得到一个 ModuleNotFoundError .如果在那之后,我开始另一个 Python 3 session ,我可以使用这些模块,例如wget ,这意味着模块已安装,但它们不适用于当前的 Python 3 session 。

是否可以在 Python 3 中安装然后在同一个 Python 3 session 中导入已安装的模块,即在安装之后?

谢谢!

编辑:

在 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()

我得到:
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'

Python 3 版本是:
user@user-VirtualBox:~$ python3 --version
Python 3.7.3
pip3版本是:
user@user-VirtualBox:~$ pip3 --version
pip 18.1 from /usr/lib/python3/dist-packages/pip (python 3.7)

其他信息:
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

有任何想法吗?

最佳答案

默认情况下,Python 在启动时会在模块搜索路径中添加用户站 pip 包目录(我将其称为 USPD)。但是这个仅当目录存在于文件系统(磁盘)上时才会发生 .我没有找到任何官方文档来支持这个声明 1 ,所以我花了一些时间调试并想知道为什么事情看起来如此奇怪。

上述行为对这个特定场景(pip install --user)有重大影响。考虑将安装模块的 Python 进程的状态(在启动时):

  • USPD 存在:
  • 事情很简单,一切正常
  • USPD 不存在:
  • 模块安装将创建它
  • 但是,由于它不在模块搜索路径中,因此安装在那里的所有模块都不能用于(简单)导入语句

  • 当另一个 Python 进程启动时,它将属于 #1。

    要解决问题,应将 USPD 手动添加到模块搜索路径中。下面是(开始的)脚本的样子:

    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 :

    1 我刚遇到[Python]: PEP 370 -- Per user site-packages directory - Implementation ( 强调 是我的):

    The site module gets a new method adduserpackage() which adds the appropriate directory to the search path. The directory is not added if it doesn't exist when Python is started.

    关于python - 在 python 3 中使用 pip 导入运行时安装的模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56974185/

    相关文章:

    python-3.x - 如何在 Azure Devops 中的另一个构建管道中使用/pip 安装自定义 Python 包工件?

    python - 在 Heroku 中获得正确的依赖

    python - 乘以两个 Pandas 数据框

    javascript - 无法让 socket.emit 处理表单值

    如果元组中的第二项是顺序的,Python 从元组中提取索引

    python - 在 python 中使用装饰器跳过单元测试

    Python计数器不识别字典

    python - 如何从 Selenium 获取元素的属性?

    python-3.x - Python - 如何将函数应用于字典

    python - 如何在 Redhat Linux 上安装 pip