python - 在 python 3 中使用 pip 导入运行时安装的模块
问题描述
我想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 会话,我可以使用这些模块,例如wget
,这意味着模块已经安装,但它们不适用于当前的 Python 3 会话。
是否可以在 Python 3 中安装然后在同一个 Python 3 会话中导入已安装的模块,即在安装后立即导入?
谢谢!
编辑:
在 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在启动时会在模块搜索路径中添加用户 site-packages 目录(我将其称为USPD )。但这只有在文件系统(磁盘)上存在目录时才会发生。我没有找到任何官方文档来支持这种说法1,所以我花了一些时间调试并想知道为什么事情看起来如此奇怪。
上述行为对这个特定场景有重大影响()。考虑将安装模块的Python进程的状态(在启动时) :pip install --user
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 -- 每个用户站点包目录 - 实施(重点是我的):
站点模块获得了一个新方法adduserpackage(),它将适当的目录添加到搜索路径中。如果在 Python 启动时该目录不存在,则不会添加该目录。
推荐阅读
- c++ - 如何在堆排序中使用用户输入数组
- reactjs - 如何更新动作创建者中的值 - 反应
- node.js - 如何在 Node.js 中使用 Express 发出请求并返回响应?
- sql - 在sql中从json创建表
- python - 合并多个数据帧与内存错误
- docker - 无法运行 docker login 错误是:保存凭据时出错:存储凭据时出错
- reactjs - 当道具数据通过反应钩子发生变化时,我想重新渲染,但我得到了无限的重新渲染
- python - 点到两条线段的距离
- authentication - 如何将 HttpClientFactory 与模拟一起使用?或者找到另一种从基于 Windows 身份的服务中获取 JWT 令牌的方法?
- assembly - MASM 在保护模式下生成错误的调用目标