Periksa apakah Paket Python diinstal


112

Apa cara yang baik untuk memeriksa apakah sebuah paket diinstal saat berada dalam skrip Python? Saya tahu itu mudah dari penerjemah, tetapi saya perlu melakukannya dalam skrip.

Saya kira saya dapat memeriksa apakah ada direktori di sistem yang dibuat selama instalasi, tetapi saya merasa ada cara yang lebih baik. Saya mencoba memastikan paket Skype4Py telah diinstal, dan jika tidak, saya akan menginstalnya.

Ide saya untuk menyelesaikan pemeriksaan

  • periksa direktori di jalur pemasangan biasa
  • coba impor paket dan jika pengecualian dibuang, maka instal paket

Menulis skrip Python untuk mengotomatiskan memulai Skype dan menggunakan tcpdump untuk mengumpulkan data paket sehingga saya dapat menganalisis bagaimana fungsi jaringan saat Anda melakukan panggilan konferensi.
Kevin

Jawaban:


107

Jika yang Anda maksud adalah skrip python, lakukan saja seperti ini:

Python 3.3+ menggunakan sys.modules dan 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
Peringatan: Saya baru saja mengalami situasi hari ini di mana ImportError dilemparkan di dalam modul itu sendiri. Ini seharusnya tidak sering terjadi, tetapi ketahuilah bahwa pemeriksaan ini tidak dapat diandalkan di semua kasus.
Koen Bok

7
Ini tidak hanya memeriksa ; itu juga mengimpornya; lihat juga stackoverflow.com/questions/14050281/…
Jorge Leitao

6
Iya. Biasanya itulah yang Anda inginkan. Anda dapat menggunakan modul alat impor untuk melakukan pemeriksaan yang lebih canggih, tetapi seringkali satu-satunya alasan Anda peduli jika modul diinstal adalah karena Anda ingin menggunakannya.
Christopher

Ini akan gagal jika Anda memiliki file lain dengan nama yang sama dengan paket.
Sapphire_Brick

Tentu, tapi itu masalah yang sama sekali berbeda. Jika Anda memiliki dua modul atau paket berbeda dengan nama yang sama di jalur pencarian Anda, Anda akan mendapat masalah.
Christopher

56

Jawaban yang diperbarui

Cara yang lebih baik untuk melakukannya adalah:

import subprocess
import sys

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

Hasil:

print(installed_packages)

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

Periksa apakah requestssudah terpasang:

if 'requests' in installed_packages:
    # Do something

Kenapa begini? Terkadang Anda mengalami benturan nama aplikasi. Mengimpor dari namespace aplikasi tidak memberi Anda gambaran lengkap tentang apa yang diinstal di sistem.

Perhatikan, solusi yang diusulkan berhasil:

  • Saat menggunakan pip untuk menginstal dari PyPI atau dari sumber alternatif lain (seperti pip install http://some.site/package-name.zipatau jenis arsip lainnya).
  • Saat menginstal secara manual menggunakan python setup.py install.
  • Saat memasang dari repositori sistem, seperti sudo apt install python-requests.

Kasus ketika itu mungkin tidak berhasil:

  • Saat memasang dalam mode pengembangan, seperti python setup.py develop.
  • Saat memasang dalam mode pengembangan, seperti pip install -e /path/to/package/source/.

Jawaban lama

Cara yang lebih baik untuk melakukannya adalah:

import pip
installed_packages = pip.get_installed_distributions()

Untuk pip> = 10.x gunakan:

from pip._internal.utils.misc import get_installed_distributions

Kenapa begini? Terkadang Anda mengalami benturan nama aplikasi. Mengimpor dari namespace aplikasi tidak memberi Anda gambaran lengkap tentang apa yang diinstal di sistem.

Hasilnya, Anda mendapatkan daftar pkg_resources.Distributionobjek. Lihat yang berikut ini sebagai contoh:

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

Buat daftarnya:

flat_installed_packages = [package.project_name for package in installed_packages]

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

Periksa apakah requestssudah terpasang:

if 'requests' in flat_installed_packages:
    # Do something

2
Seperti yang disebutkan dalam jawaban lain, ada kemungkinan bahwa kesalahan tidak tertangkap. Oleh karena itu saya pikir ini harus menjadi jawaban yang diterima.
Jorrick Sleijster

1
Metode ini tidak bekerja dengan paket seperti 'json' (mengembalikan False saat import jsonbenar-benar berfungsi). Metode ice.nicer bekerja dalam kasus ini.
mountrix

1
Entah bagaimana saya perlu menggunakan cek if "u'requests'" in installed_packages:dari Jawaban yang Diperbarui untuk bekerja untuk saya. Output dari print()menghasilkan ini pada macOS python saya:[..., u'pytz', u'requests', ...]
Buju

1
@ArturBarseghyan Saya menggunakan Python 2.7.10 (sistem macOS python) ... sebenarnya saya harus menggunakan if "requests'"(perhatikan kutipan tunggal di bagian akhir). tidak masuk akal sama sekali.
Buju

1
Ini tidak menjawab pertanyaan: "apakah paket 'x' diinstal?". Ada banyak cara untuk menginstal paket tanpa menggunakan pip. Misalnya, Anda dapat membuat dan menginstal paket dari sumber. Jawaban ini tidak akan menemukannya. Jawaban dari @ ice.nicer tentang find_spec()benar.
Arthur

43

Pada Python 3.3, Anda dapat menggunakan find_spec () metode

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
Bersih dan sederhana, jawaban terbaik di sini. Ini membutuhkan lebih banyak suara positif.
David Parks

5
Hati-hati. Jika nama paket berisi tanda hubung, find_spec () tidak dapat menemukannya kecuali Anda menggunakan titik. Contoh: importlib.util.find_spec('google-cloud-logging')tidak menemukan apa pun saat importlib.util.find_spec('google.cloud.logging')ditemukan. Nama dan nama resmi yang ditampilkan pip adalah dengan tanda hubung, bukan titik. Mungkin membingungkan karena itu gunakan dengan hati-hati.
dwich

27

Jika Anda ingin mendapatkan cek dari terminal, Anda dapat menjalankannya

pip3 show package_name

dan jika tidak ada yang dikembalikan, paket tersebut tidak diinstal.

Jika mungkin Anda ingin mengotomatiskan pemeriksaan ini, sehingga misalnya Anda dapat menginstalnya jika hilang, Anda dapat memiliki yang berikut ini di skrip bash Anda:

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

Ini tampak hebat tetapi selalu mengembalikan "Not Installed" untuk saya. Mengapa?
Elliptica

Dapatkah Anda membagikan output dari "$ pip3 —version" dan "$ pip3 show package_name", di mana Anda mengganti package_name dengan paket yang diinginkan?
Ognjen Vukovic

Tip shell: Anda dapat menggunakan ifuntuk langsung menguji perintah yang berhasil:if pip3 show package_name 1>/dev/null; then ...
MestreLion

6

Sebagai perpanjangan dari jawaban ini :

Untuk Python 2. *, pip show <package_name>akan melakukan tugas yang sama.

Misalnya pip show numpyakan mengembalikan yang berikut atau serupa:

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

Bukan dari skrip tetapi bagus untuk pemeriksaan baris perintah. Terima kasih
Jj Rivero

3

Anda dapat menggunakan modul pkg_resources dari setuptools. Sebagai contoh:

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)

Perhatikan bahwa ada perbedaan antara modul python dan paket python. Sebuah paket dapat berisi beberapa modul dan nama modul mungkin tidak cocok dengan nama paket.



1

Saya ingin menambahkan beberapa pemikiran / temuan saya ke topik ini. Saya sedang menulis skrip yang memeriksa semua persyaratan untuk program yang dibuat khusus. Ada banyak pemeriksaan dengan modul python juga.

Ada sedikit masalah dengan

try:
   import ..
except:
   ..

larutan. Dalam kasus saya, salah satu modul python dipanggil python-nmap, tetapi Anda mengimpornya dengan import nmapdan seperti yang Anda lihat nama tidak cocok. Oleh karena itu pengujian dengan solusi di atas mengembalikan hasil False, dan juga mengimpor modul saat dipukul, tetapi mungkin tidak perlu menggunakan banyak memori untuk pengujian / pemeriksaan sederhana.

Saya juga menemukan itu

import pip
installed_packages = pip.get_installed_distributions()

installed_packagesakan memiliki hanya paket telah diinstal dengan pip . Pada sistem saya pip freezemengembalikan 40modul python, sementara installed_packageshanya memiliki 1, yang saya instal secara manual (python-nmap).

Solusi lain di bawah ini yang saya tahu mungkin tidak relevan dengan pertanyaan tersebut , tetapi menurut saya merupakan praktik yang baik untuk menjaga fungsi pengujian tetap terpisah dari yang melakukan penginstalan, mungkin berguna bagi sebagian orang.

Solusi yang berhasil untuk saya. Itu berdasarkan jawaban ini Bagaimana memeriksa apakah modul python ada tanpa mengimpornya

from imp import find_module

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

CATATAN: solusi ini tidak dapat menemukan modul dengan namanya python-nmapjuga, saya harus menggunakan nmapsebagai gantinya (mudah digunakan ) tetapi dalam hal ini modul tidak akan dimuat ke memori sama sekali.


0

Jika Anda ingin skrip Anda menginstal paket yang hilang dan melanjutkan, Anda dapat melakukan sesuatu seperti ini (pada contoh modul 'krbV' dalam paket 'python-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

Cara cepat adalah dengan menggunakan alat baris perintah python . Cukup ketik import <your module name> Anda melihat kesalahan jika modul hilang.

$ 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

Hmmm ... jawaban terdekat yang saya lihat adalah menggunakan baris perintah untuk mencoba mengimpor. Tapi saya lebih suka menghindari itu.

Bagaimana dengan 'pip freeze | grep pkgname '? Saya mencobanya dan berhasil dengan baik. Ini juga menunjukkan kepada Anda versi yang dimilikinya dan apakah itu diinstal di bawah kontrol versi (instal) atau diedit (kembangkan).


0

class myError (pengecualian): lulus #atau lakukan sesuatu coba: impor mymodule kecuali ImportError sebagai e: menaikkan myError ("terjadi kesalahan")


0

Di tipe Terminal

pip show some_package_name

Contoh

pip show matplotlib

0

Saya ingin mengomentari balasan @ ice.nicer tetapi saya tidak bisa, jadi ... Pengamatan saya adalah bahwa paket dengan tanda hubung disimpan dengan garis bawah, tidak hanya dengan titik seperti yang ditunjukkan oleh komentar @dwich

Misalnya, Anda melakukannya pip3 install sphinx-rtd-theme, tetapi:

  • importlib.util.find_spec(sphinx_rtd_theme) mengembalikan sebuah Objek
  • importlib.util.find_spec(sphinx-rtd-theme) mengembalikan Tidak ada
  • importlib.util.find_spec(sphinx.rtd.theme) memunculkan ModuleNotFoundError

Apalagi beberapa nama berubah total. Misalnya, Anda melakukannya pip3 install pyyamltetapi disimpan sebagai fileyaml

Saya menggunakan python3.8


0
if pip3 list | grep -sE '^some_command\s+[0-9]' >/dev/null
  # installed ...
else
  # not installed ...
fi

-1

Pergi opsi # 2. Jika ImportErrordilempar, maka paket tersebut tidak diinstal (atau tidak di sys.path).

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.