54

私は書くことができるようになりたいです:

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

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

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

4

4 に答える 4

59

反対票を投じるリスクがあるので、簡単なハックを提案したいと思います。依存関係は外部で管理する必要があるという受け入れられた回答に完全に参加していることに注意してください。

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

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
于 2016-04-21T06:45:06.733 に答える
40

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

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

それが道です... anの結果として何かをインストールするのImportError は、ちょっと奇妙で怖いです。やらないでください。

于 2011-05-25T07:30:54.913 に答える
35
try:
    import foo
except ImportError:
    sys.exit("""You need foo!
                install it from http://pypi.python.org/pypi/foo
                or run pip install foo.""")

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

于 2011-05-25T07:29:16.930 に答える
10

これが私がまとめたソリューションですpyInstall.py。実際には、モジュールがインストールされているかどうかをチェックします(私の意見では、これを/ではなくでImportError処理した方がきれいに見えます)。iftryexcept

バージョン 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 では、元の回答のコードを使用する方がよい場合があります。

于 2014-09-03T12:12:03.050 に答える