我希望能够写下:
try:
import foo
except ImportError:
install_the_module("foo")
处理此方案的推荐/惯用方法是什么?
我看过很多脚本只是打印错误或警告,通知用户有关丢失的模块,并(有时)提供有关如何安装的说明。但是,如果我知道该模块在PyPI上可用,那么我可以更进一步地启动安装过程。否?
答案 0 :(得分:25)
安装问题不受源代码约束!
您可以在程序包的setup.py
内正确定义依赖项
使用install_requires
配置。
这是要走的路......由ImportError
安装的东西
有点奇怪和可怕。不要这样做。
答案 1 :(得分:22)
try:
import foo
except ImportError:
sys.exit("""You need foo!
install it from http://pypi.python.org/pypi/foo
or run pip install foo.""")
请勿触摸用户的安装。
答案 2 :(得分:18)
冒险负面投票,我想建议一个快速的黑客。请注意我完全接受了已接受的答案,应该在外部管理相关性。
但是对于你绝对需要攻击像自包含的东西的情况,你可以尝试类似下面的东西:
import os
try:
import requests
except ImportError:
print "Trying to Install required module: requests\n"
os.system('python -m pip install requests')
# -- above lines try to install requests module if not present
# -- if all went well, import required module again ( for global access)
import requests
答案 3 :(得分:6)
这是我放在一起的解决方案,我称之为pyInstall.py
。它实际上会检查模块是否已安装而不是依赖于ImportError
(在我看来,它只是看起来更清晰,以if
而不是try
/ {{1}来处理})。
我在版本2.6和2.7下使用它...如果我不想将except
作为一个函数来处理它可能适用于旧版本......我认为它可以在版本3.0+但我从未尝试过。
另外,正如我在print
函数的注释中所述,我认为特定功能在OS X下不起作用。
getPip
以下是一些使用示例:
from __future__ import print_function
from subprocess import call
def installPip(log=print):
"""
Pip is the standard package manager for Python. Starting with Python 3.4
it's included in the default installation, but older versions may need to
download and install it. This code should pretty cleanly do just that.
"""
log("Installing pip, the standard Python Package Manager, first")
from os import remove
from urllib import urlretrieve
urlretrieve("https://bootstrap.pypa.io/get-pip.py", "get-pip.py")
call(["python", "get-pip.py"])
# Clean up now...
remove("get-pip.py")
def getPip(log=print):
"""
Pip is the standard package manager for Python.
This returns the path to the pip executable, installing it if necessary.
"""
from os.path import isfile, join
from sys import prefix
# Generate the path to where pip is or will be installed... this has been
# tested and works on Windows, but will likely need tweaking for other OS's.
# On OS X, I seem to have pip at /usr/local/bin/pip?
pipPath = join(prefix, 'Scripts', 'pip.exe')
# Check if pip is installed, and install it if it isn't.
if not isfile(pipPath):
installPip(log)
if not isfile(pipPath):
raise("Failed to find or install pip!")
return pipPath
def installIfNeeded(moduleName, nameOnPip=None, notes="", log=print):
""" Installs a Python library using pip, if it isn't already installed. """
from pkgutil import iter_modules
# Check if the module is installed
if moduleName not in [tuple_[1] for tuple_ in iter_modules()]:
log("Installing " + moduleName + notes + " Library for Python")
call([getPip(log), "install", nameOnPip if nameOnPip else moduleName])
编辑:获取pipPath的更多跨平台方式是:
from datetime import datetime
from pyInstall import installIfNeeded
# I like to have my messages timestamped so I can get an idea of how long they take.
def log(message):
print(datetime.now().strftime("%a %b %d %H:%M:%S") + " - " + str(message))
# The name fabric doesn't really convey to the end user why the module is needed,
# so I include a very quick note that it's used for SSH.
installIfNeeded("fabric", notes = " (ssh)", log = log)
# SoftLayer is actually named softlayer on pip.
installIfNeeded("SoftLayer", "softlayer", log = log)
这假设from subprocess import Popen, PIPE
finder = Popen(['where' if isWindows() else 'which', 'pip'], stdout = PIPE, stderr = PIPE)
pipPath = finder.communicate()[0].strip()
将被安装在系统路径上。它在非Windows平台上往往非常可靠,但在Windows上,最好在原始答案中使用该代码。