【问题标题】:Installing python module within code在代码中安装 python 模块
【发布时间】:2012-09-02 05:09:40
【问题描述】:

我需要直接在我的脚本中安装来自 PyPi 的包。 也许有一些模块或distutilsdistributepip 等)功能允许我执行类似pypi.install('requests') 的操作,并且请求将安装到我的 virtualenv 中。

【问题讨论】:

  • 为什么不在自己包的setup.py中定义相关模块为依赖呢?
  • 你知道......它实际上应该做的方式......但你总是可以 os.system("pip install blah") 但你可能需要 sudo 访问......最好只是使其成为 setup.py 中的依赖项
  • 您会考虑在这里更改接受的答案吗?导入 pip 从来都不是一个好主意 - 从版本 10 开始,它的所有内容都在 _internal 中......
  • @chuwy stackoverflow.com/a/50255019/918959 pip._internal 不是为可导入而设计的,当导入另一个程序时,它可以做绝对随机的事情。
  • @AnttiHaapala 好的,我改了。我个人不喜欢这两种解决方案,但这些天我离 Python 还很远,所以我相信你的意见。

标签: python pip python-module pypi


【解决方案1】:

您使用“install_requires”选项在您自己的包的 setup.py 中定义依赖模块。

如果您的包需要生成一些控制台脚本,那么您可以使用“console_scripts”入口点来生成将放置的包装脚本 在“bin”文件夹中(例如您的 virtualenv 环境)。

【讨论】:

  • 这是正确的答案,也是管理 Python 项目依赖项的唯一明智方法。它将与 virtualenv、Fabric、buildout 一起使用,你可以命名它。 @xiaomao 描述的方法,即使完全回答了 OP 的要求,也是纯粹的疯狂。
  • 虽然这是正确的建议,但它并没有回答所提出的问题
  • 虽然打包是一个主题,但还有很多其他用例,例如用 python 编写的部署脚本。
【解决方案2】:

这应该可行:

import subprocess

def install(name):
    subprocess.call(['pip', 'install', name])

【讨论】:

  • 是的,它肯定可以工作。但我认为有更优雅的方式;)我会等一会儿,可能有。
  • @Downvoter:我的回答到底有什么问题?这个答案有所有OP想要的。它甚至不使用外壳。
  • 这取决于正确的 pip 版本是否在路径上。如果用户正在运行备用 python 安装,pip 将安装到第一个而不是当前安装。上面的导入方法将安装在正确的位置。无论如何,我投了反对票。
  • 根据脚本的运行方式,您不会调用正确的 pip。
  • 致电[sys.executable, '-m', 'pip', 'install', name] 确保在此处获得“正确”点数。
【解决方案3】:

你也可以使用类似的东西:

import pip

def install(package):
    if hasattr(pip, 'main'):
        pip.main(['install', package])
    else:
        pip._internal.main(['install', package])

# Example
if __name__ == '__main__':
    install('argh')

【讨论】:

【解决方案4】:

如果你想使用pip安装所需的包并在安装后导入,你可以使用这个代码:

def install_and_import(package):
    import importlib
    try:
        importlib.import_module(package)
    except ImportError:
        import pip
        pip.main(['install', package])
    finally:
        globals()[package] = importlib.import_module(package)


install_and_import('transliterate')

如果您以用户身份安装包,您可能会遇到无法仅导入包的问题。更多信息请参见How to refresh sys.path?

【讨论】:

  • 知道如何在 Python 3 上做到这一点吗? imp.reload(site)让我RuntimeError: dictionary changed size during iteration
  • 这在哪里安装包,在我这样做之后,我无法做到pip uninstall <package_name>。我仍然可以使用pip.main 卸载它,但只是想知道它在哪里安装包?
  • 很好奇。如果我这样做会正常工作:pip install requests[security]?我不确定它是否能正确定义全局变量。
  • 在函数中导入是否真的导入到主命名空间,或者只是 install_and_import 函数的命名空间?
【解决方案5】:

官方推荐的从脚本安装包的方法是通过子进程调用 pip 的命令行界面。 Most other answers presented here are not supported by pip。此外,从 pip v10 开始,所有代码都已移至 pip._internal,正是为了向用户明确表示不允许以编程方式使用 pip。

使用sys.executable 确保您将调用与当前运行时关联的相同pip

import subprocess
import sys

def install(package):
    subprocess.check_call([sys.executable, "-m", "pip", "install", package])

【讨论】:

  • 这样做的一个问题是,对于 Windows 上的新手用户,python 和 pip 并不总是在他们的 PATH 上,因此可以双击的 .py 文件会非常方便,而“pip install xxx”评论可能很棘手。
  • CalledProcessError: Command '['C:\\ProgramData\\Anaconda3\\pythonw.exe', '-m', 'pip', 'install', 'googleapiclient']' 返回非零退出状态 1.
  • 我正在尝试使用这种方法,但是我的 python 是从另一个可执行文件嵌入/启动的,因此“sys.executable”不会返回正确的路径。是否有替代方案适用于由其他进程启动的 python?
【解决方案6】:

我在@Aaron 的回答中添加了一些异常处理。

import subprocess
import sys

try:
    import pandas as pd
except ImportError:
    subprocess.check_call([sys.executable, "-m", "pip", "install", 'pandas'])
finally:
    import pandas as pd

【讨论】:

  • 子流程和 pip 的不错实现,比这里的大多数解决方案都好
  • 您没有检查subprocess.call 的返回值,因此代码可能会失败。
  • 为什么是subprocess.check_call 而不是subprocess.call
  • 好吧,运行“import pandas as pd”没有问题,但是……逻辑上是不是很丑?
【解决方案7】:

为了安装多个包,我使用setup.py 文件,代码如下:

import sys
import subprocess
import pkg_resources

required  = {'numpy', 'pandas', '<etc>'} 
installed = {pkg.key for pkg in pkg_resources.working_set}
missing   = required - installed

if missing:
    # implement pip as a subprocess:
    subprocess.check_call([sys.executable, '-m', 'pip', 'install', *missing])

【讨论】:

【解决方案8】:
import os
os.system('pip install requests')

我在上面尝试了临时解决方案,而不是更改 docker 文件。希望这些可能对某些人有用

【讨论】:

  • 与所有其他答案相比,这对于初学者来说非常容易理解。非常感谢。
【解决方案9】:

试试下面的。迄今为止最适合我的 先安装 4 个,然后在 REQUIRED 列表中提及新的

import pkg_resources
import subprocess
import sys
import os

REQUIRED = {
  'spacy', 'scikit-learn', 'numpy', 'pandas', 'torch', 
  'pyfunctional', 'textblob', 'seaborn', 'matplotlib'
}

installed = {pkg.key for pkg in pkg_resources.working_set}
missing = REQUIRED - installed

if missing:
    python = sys.executable
    subprocess.check_call([python, '-m', 'pip', 'install', *missing], stdout=subprocess.DEVNULL)

【讨论】:

  • 这只是 Tanmay Shrivastava 回答的副本
【解决方案10】:

如果您想要在subprocess.check_call 上扩展的更有效的答案。您可以先使用pkg_resources 检查是否已满足要求。

这适用于不同的requirment specifiers,这很好。例如&gt;=, ==

import sys
import subprocess
import pkg_resources
from pkg_resources import DistributionNotFound, VersionConflict

def should_install_requirement(requirement):
    should_install = False
    try:
        pkg_resources.require(requirement)
    except (DistributionNotFound, VersionConflict):
        should_install = True
    return should_install


def install_packages(requirement_list):
    try:
        requirements = [
            requirement
            for requirement in requirement_list
            if should_install_requirement(requirement)
        ]
        if len(requirements) > 0:
            subprocess.check_call([sys.executable, "-m", "pip", "install", *requirements])
        else:
            print("Requirements already satisfied.")

    except Exception as e:
        print(e)

示例用法:

requirement_list = ['requests', 'httpx==0.18.2']
install_packages(requirement_list)

相关信息Stackoverflow Question: 58612272

【讨论】:

    【解决方案11】:

    有条件地安装多个具有精确版本的软件包,我一直在根据@Tanmay Shrivastava 的回答使用这种模式:

    import sys
    from subprocess import run, PIPE, STDOUT
    import pkg_resources
    
    def run_cmd(cmd):
        ps = run(cmd, stdout=PIPE, stderr=STDOUT, shell=True, text=True)
        print(ps.stdout)
    
    
    # packages to be conditionally installed with exact version
    required = {"click==8.0.1", "semver==3.0.0.dev2"}
    installed = {f"{pkg.key}=={pkg.version}" for pkg in pkg_resources.working_set}
    missing = required - installed
    
    if missing:
        run_cmd(f'pip install --ignore-installed {" ".join([*missing])}')
    

    【讨论】:

      猜你喜欢
      • 2016-03-14
      • 2020-04-21
      • 2023-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多