web-dev-qa-db-ja.com

欠落しているpythonモジュールを自動的にインストールするにはどうすればよいですか?

私は書きたいと思います:

try:
    import foo
except ImportError:
    install_the_module("foo")

このシナリオを処理する推奨/慣用的な方法は何ですか?

多くのスクリプトが、不足しているモジュールについてユーザーに通知し、(場合によっては)インストール方法に関する指示を提供するエラーまたは警告を出力するだけです。ただし、モジュールが PyPI で利用可能であることがわかっている場合は、インストールプロセスを開始するためにこれをさらに一歩進めることができます。番号?

33
j b

インストールの問題はソースコードの対象ではありません!

setup.py構成を使用して、パッケージのinstall_requires内で依存関係を適切に定義します。

ImportErrorの結果として何かをインストールするのは...奇妙で恐ろしいことです。しないでください。

26
Andreas Jung
try:
    import foo
except ImportError:
    sys.exit("""You need foo!
                install it from http://pypi.python.org/pypi/foo
                or run pip install foo.""")

ユーザーのインストールに触れないでください。

22
CharlesB

反対票を投じるリスクを冒して、簡単なハックを提案したいと思います。 私は完全に受け入れられた答えを持っている依存関係は外部で管理されるべきであることに注意してください。

ただし、自己完結型のように振る舞うものを絶対にハックする必要がある場合は、次のようなものを試すことができます。

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
19
ring bearer

これが私がまとめた解決策ですpyInstall.py。モジュールがImportErrorに依存するのではなく、実際にインストールされているかどうかを実際にチェックします(私の意見では、if/tryではなくexceptでこれを処理するほうがきれいに見えます)。

バージョン2.6および2.7で使用しました... printを関数として処理したくない場合、おそらく古いバージョンで動作します...そして、バージョン3.0+で動作すると思いますが、試したことがない。

また、getPip関数のコメントで述べているように、特定の関数がOS Xで機能するとは思わない。

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])

以下に使用例を示します。

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)

編集:よりクロスプラットフォームなpipPathの取得方法:

from subprocess import Popen, PIPE
Finder = Popen(['where' if isWindows() else 'which', 'pip'], stdout = PIPE, stderr = PIPE)
pipPath = Finder.communicate()[0].strip()

これは、pipがシステムパスにインストールされる/されることを前提としています。 Windows以外のプラットフォームではかなり信頼性が高い傾向がありますが、Windowsでは、元の回答のコードを使用した方が良い場合があります。

6
ArtOfWarfare