Pythonパッケージがインストールされているかどうかを確認する


112

Pythonスクリプト内でパッケージがインストールされているかどうかを確認する良い方法は何ですか?インタプリタからは簡単ですが、スクリプト内で実行する必要があります。

インストール中に作成されたディレクトリがシステムにあるかどうかは確認できたと思いますが、もっと良い方法があると思います。Skype4Pyパッケージがインストールされていることを確認しようとしています。インストールされていない場合は、インストールします。

チェックを達成するための私のアイデア

  • 一般的なインストールパスのディレクトリを確認します
  • パッケージのインポートを試み、例外がスローされた場合はパッケージをインストールします

Skypeの起動を自動化するためのPythonスクリプトを記述し、tcpdumpを使用してパケットデータを収集することで、電話会議の際のネットワークの機能を分析できるようにします。
ケビン

回答:


107

Pythonスクリプトの場合は、次のようにします。

Pythonの3.3+使用sys.modulesとfind_spec

import importlib.util
import sys

# For illustrative purposes.
name = 'itertools'

if name in sys.modules:
    print(f"{name!r} already in sys.modules")
elif (spec := importlib.util.find_spec(name)) is not None:
    # If you choose to perform the actual import ...
    module = importlib.util.module_from_spec(spec)
    sys.modules[name] = module
    spec.loader.exec_module(module)
    print(f"{name!r} has been imported")
else:
    print(f"can't find the {name!r} module")

Python 3:

try:
    import mymodule
except ImportError as e:
    pass  # module doesn't exist, deal with it.

Python 2:

try:
    import mymodule
except ImportError, e:
    pass  # module doesn't exist, deal with it.

6
警告:ImportErrorがモジュール自体の内部でスローされた状況が今日ありました。これは頻繁に起こるべきではありませんが、このチェックはすべての場合に信頼できるとは限らないことに注意してください。
Koen Bok

7
これはチェックだけではありません。それもインポートします。stackoverflow.com/questions/14050281/…
Jorge Leitao 2014年

6
はい。それが一般的に必要なことです。インポートツールモジュールを使用してより高度なチェックを行うことができますが、ほとんどの場合、モジュールがインストールされているかどうかを気にする唯一の理由は、そのモジュールを使用するためです。
クリストファー

パッケージと同じ名前の別のファイルがある場合、これは失敗します。
Sapphire_Brick

もちろん、それはまったく別の問題です。ルックアップパスに同じ名前の2つの異なるモジュールまたはパッケージがある場合、問題が発生します。
クリストファー

56

回答を更新しました

これを行うより良い方法は次のとおりです。

import subprocess
import sys

reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'])
installed_packages = [r.decode().split('==')[0] for r in reqs.split()]

結果:

print(installed_packages)

[
    "Django",
    "six",
    "requests",
]

requestsがインストールされているかどうかを確認します。

if 'requests' in installed_packages:
    # Do something

なぜこのように?アプリ名が競合する場合があります。アプリの名前空間からインポートしても、システムにインストールされているものの全体像はわかりません。

提案されたソリューションが機能することに注意してください:

  • Pipを使用して、PyPIまたはその他の代替ソース(pip install http://some.site/package-name.zipまたはその他の種類のアーカイブ)からインストールする場合。
  • を使用して手動でインストールする場合python setup.py install
  • のようなシステムリポジトリからインストールする場合sudo apt install python-requests

うまくいかない場合:

  • のような開発モードでインストールする場合python setup.py develop
  • のような開発モードでインストールする場合pip install -e /path/to/package/source/

古い答え

これを行うより良い方法は次のとおりです。

import pip
installed_packages = pip.get_installed_distributions()

pip> == 10.xの場合:

from pip._internal.utils.misc import get_installed_distributions

なぜこのように?アプリ名が競合する場合があります。アプリの名前空間からインポートしても、システムにインストールされているものの全体像はわかりません。

その結果、pkg_resources.Distributionオブジェクトのリストを取得します。例として次を参照してください。

print installed_packages
[
    "Django 1.6.4 (/path-to-your-env/lib/python2.7/site-packages)",
    "six 1.6.1 (/path-to-your-env/lib/python2.7/site-packages)",
    "requests 2.5.0 (/path-to-your-env/lib/python2.7/site-packages)",
]

それのリストを作る:

flat_installed_packages = [package.project_name for package in installed_packages]

[
    "Django",
    "six",
    "requests",
]

requestsがインストールされているかどうかを確認します。

if 'requests' in flat_installed_packages:
    # Do something

2
他の回答で述べたように、エラーがキャッチされない可能性があります。したがって、これは受け入れられる答えであると思います。
Jorrick Sleijster 2017

1
このメソッドは「json」などのパッケージでは機能しません(import json実際に機能している場合はFalseを返します)。この場合、ice.nicerのメソッドが機能しています。
mountrix 2018

1
どういうわけか私のためにif "u'requests'" in installed_packages:更新された回答からのチェックを使用する必要がありました。出力は、print()私のMacOSのpythonでこれを生成します:[..., u'pytz', u'requests', ...]
Buju

1
@ArturBarseghyan私はPython 2.7.10(macOSシステムpython)を使用しています...実際に使用する必要がありますif "requests'"(末尾の単一引用符に注意してください)。まったく意味がありません。
Buju

1
これは「パッケージ 'x'はインストールされていますか?」という質問には答えません。を使用せずにパッケージをインストールする方法はたくさんありますpip。たとえば、ソースからパッケージを作成してインストールできます。この答えはそれらを見つけられません。@ ice.nicerからの答えfind_spec()は正しいです。
アーサー

43

Python 3.3以降では、find_spec()メソッドを使用できます

import importlib.util

# For illustrative purposes.
package_name = 'pandas'

spec = importlib.util.find_spec(package_name)
if spec is None:
    print(package_name +" is not installed")

4
クリーンでシンプルな、ここでの最良の答え。これにはもっと賛成票が必要です。
David Parks

5
注意してください。パッケージ名にダッシュが含まれている場合、ドットを使用しない限り、find_spec()はそれを見つけることができません。例:importlib.util.find_spec('google-cloud-logging')が見つかっても何も見つかりませんimportlib.util.find_spec('google.cloud.logging')。公式名とpipが表示する名前は、ドットではなくダッシュ付きです。混乱する可能性があるため、注意して使用してください。
dwich

27

ターミナルからチェックしたい場合は、実行できます

pip3 show package_name

何も返されない場合、パッケージはインストールされていません。

このチェックを自動化して、たとえば、インストールされていない場合にインストールできるようにする場合は、bashスクリプトに以下を含めることができます。

pip3 show package_name 1>/dev/null #pip for Python 2
if [ $? == 0 ]; then
   echo "Installed" #Replace with your actions
else
   echo "Not Installed" #Replace with your actions, 'pip3 install --upgrade package_name' ?
fi

これは素晴らしいように見えますが、私にとっては常に「未インストール」を返します。どうして?
Elliptica

「$ pip3 —version」および「$ pip3 show package_name」の出力を共有できますか。package_nameを目的のパッケージに置き換えますか?
Ognjen Vukovic

シェルのヒント:あなたが使用することができif、直接成功したコマンドをテストするために:if pip3 show package_name 1>/dev/null; then ...
MestreLion

6

この回答の延長として:

Python 2. *の場合pip show <package_name>、同じタスクを実行します。

たとえばpip show numpy、次のようなものを返します。

Name: numpy
Version: 1.11.1
Summary: NumPy: array processing for numbers, strings, records, and objects.
Home-page: http://www.numpy.org
Author: NumPy Developers
Author-email: numpy-discussion@scipy.org
License: BSD
Location: /home/***/anaconda2/lib/python2.7/site-packages
Requires: 
Required-by: smop, pandas, tables, spectrum, seaborn, patsy, odo, numpy-stl, numba, nfft, netCDF4, MDAnalysis, matplotlib, h5py, GridDataFormats, dynd, datashape, Bottleneck, blaze, astropy

スクリプトからではなく、コマンドラインチェックに最適です。ありがとう
Jj Rivero

3

setuptoolsからpkg_resourcesモジュールを使用できます。例えば:

import pkg_resources

package_name = 'cool_package'
try:
    cool_package_dist_info = pkg_resources.get_distribution(package_name)
except pkg_resources.DistributionNotFound:
    print('{} not installed'.format(package_name))
else:
    print(cool_package_dist_info)

pythonモジュールとpythonパッケージには違いがあることに注意してください。パッケージには複数のモジュールを含めることができ、モジュールの名前はパッケージ名と一致しない場合があります。



1

このトピックに私の考え/調査結果をいくつか追加したいと思います。カスタムメイドプログラムのすべての要件をチェックするスクリプトを書いています。Pythonモジュールのチェックもたくさんあります。

に少し問題があります

try:
   import ..
except:
   ..

解決。私の場合、Pythonモジュールの1つがと呼ばれてpython-nmapいますが、それをインポートするとimport nmap、名前が一致しなくなります。したがって、上記のソリューションを使用したテストはFalseの結果を返し、ヒット時にモジュールをインポートしますが、単純なテスト/チェックのために大量のメモリを使用する必要はないかもしれません。

私もそれを見つけました

import pip
installed_packages = pip.get_installed_distributions()

installed_packages必要がありますパッケージのみをされていピップでインストール。私のシステムでpip freeze40pythonモジュール経由で戻りますが、手動でインストールしたもの(python-nmap)installed_packagesしかありません1

以下の別の解決策は、質問関連しない可能性があることを知っています、テスト機能を、インストールを実行するものとは別にしておくと、一部のユーザーにとって役立つ場合があるので、良い方法だと思います。

私のために働いた解決策。それはこの回答に基づいていますインポートせずにPythonモジュールが存在するかどうかを確認する方法

from imp import find_module

def checkPythonmod(mod):
    try:
        op = find_module(mod)
        return True
    except ImportError:
        return False

注:この解決策ではモジュールを名前で見つけることもできません。代わりに(使いやすい)をpython-nmap使用する必要がありますnmapが、この場合、モジュールはメモリにロードされません。


0

スクリプトで不足しているパッケージをインストールして続行する場合は、次のようにします( 'python-krbV'パッケージの 'krbV'モジュールの例):

import pip
import sys

for m, pkg in [('krbV', 'python-krbV')]:
    try:
        setattr(sys.modules[__name__], m, __import__(m))
    except ImportError:
        pip.main(['install', pkg])
        setattr(sys.modules[__name__], m, __import__(m))

0

簡単な方法は、pythonコマンドラインツールを使用することです。「import <your module name> モジュールが見つからない場合はエラーが表示されます」と入力します。

$ python
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
>>> import sys
>>> import jocker
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named jocker
$

0

うーん...便利な答えに一番近いのは、コマンドラインを使用してインポートを試すことでした。しかし、私はそれを避けたいのです。

ピップフリーズはどうですか?grep pkgname '?私はそれを試しました、そしてそれはうまくいきます。また、バージョンと、バージョン管理下にインストールされているか(インストール)、編集可能か(開発)も表示されます。


0

クラスmyError(exception):pass #or何かを試してみてください:ImportError以外のmymoduleをeとしてインポートします:myErrorを発生させます( "エラーが発生しました")



0

@ ice.nicerの返信にコメントしたいのですが、コメントできません。そのため 、ダッシュを含むパッケージは、@ dwichコメントで指摘されたドットだけでなく、アンダースコアで保存されます。

たとえば、次のようにしますがpip3 install sphinx-rtd-theme

  • importlib.util.find_spec(sphinx_rtd_theme) オブジェクトを返します
  • importlib.util.find_spec(sphinx-rtd-theme) Noneを返します
  • importlib.util.find_spec(sphinx.rtd.theme) ModuleNotFoundErrorを発生させます

また、一部の名称は完全に変更されています。たとえば、あなたはそうしますがpip3 install pyyaml、それは単に次のように保存されますyaml

私はpython3.8を使用しています



-1

オプション#2に進みます。ImportErrorがスローされた場合、パッケージはインストールされていません(またはにありませんsys.path)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.