Python Paketinin kurulu olup olmadığını kontrol edin


113

Python komut dosyası içindeyken bir paketin kurulup kurulmadığını kontrol etmenin iyi bir yolu nedir? Tercümandan kolay olduğunu biliyorum, ama bunu bir senaryo içinde yapmam gerekiyor.

Kurulum sırasında sistemde oluşturulan bir dizin olup olmadığını kontrol edebilirim, ancak daha iyi bir yol varmış gibi hissediyorum. Skype4Py paketinin kurulu olduğundan emin olmaya çalışıyorum, yoksa yükleyeceğim.

Kontrolü tamamlamak için fikirlerim

  • tipik kurulum yolunda bir dizini kontrol edin
  • paketi içe aktarmayı deneyin ve bir istisna atılırsa paketi kurun

Skype'ı başlatmayı otomatikleştirmek için bir Python betiği yazmak ve paket verilerini toplamak için tcpdump kullanmak, böylece bir konferans görüşmeniz olduğunda ağın nasıl çalıştığını analiz edebiliyorum.
Kevin

Yanıtlar:


108

Bir python komut dosyası demek istiyorsan, şöyle bir şey yap:

Python 3.3+ sys.modules ve find_spec'i kullanır :

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
Uyarı: Bugün ImportError'ın modülün içine fırlatıldığı bir durumla karşılaştım. Bu sık sık gerçekleşmemelidir, ancak bu kontrolün her durumda güvenilir olmadığını unutmayın.
Koen Bok

7
Bu sadece kontrol etmekle kalmaz ; ayrıca ithal ediyor; ayrıca bkz. stackoverflow.com/questions/14050281/…
Jorge Leitao

6
Evet. Genelde istediğin bu. Daha karmaşık bir kontrol yapmak için içe aktarma araçları modülünü kullanabilirsiniz, ancak çoğu zaman bir modülün takılı olmasını önemsemenizin tek nedeni onu kullanmak istemenizdir.
Christopher

Paketle aynı ada sahip başka bir dosyanız varsa bu başarısız olur.
Sapphire_Brick

Elbette, ama bu tamamen farklı bir sorun. Arama yolunuzda aynı adı taşıyan iki farklı modül veya paketiniz varsa başınız belada demektir.
Christopher

56

Güncellenen cevap

Bunu yapmanın daha iyi bir yolu şudur:

import subprocess
import sys

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

Sonuç:

print(installed_packages)

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

requestsKurulu olup olmadığını kontrol edin :

if 'requests' in installed_packages:
    # Do something

Neden bu şekilde? Bazen uygulama adı çakışmalarınız olur. Uygulama ad alanından içe aktarmak, sistemde yüklü olanların tam resmini vermez.

Önerilen çözümün işe yaradığını unutmayın:

  • PyPI'den veya başka herhangi bir alternatif kaynaktan (benzer pip install http://some.site/package-name.zipveya başka herhangi bir arşiv türü) yüklemek için pip kullanırken .
  • Kullanarak manuel olarak kurarken python setup.py install.
  • Sistem depolarından yüklerken, gibi sudo apt install python-requests.

Kılıflar o olabilir değil çalışır:

  • Geliştirme modunda yüklerken, gibi python setup.py develop.
  • Geliştirme modunda yüklerken, gibi pip install -e /path/to/package/source/.

Eski cevap

Bunu yapmanın daha iyi bir yolu şudur:

import pip
installed_packages = pip.get_installed_distributions()

Pip> = 10.x için kullanım:

from pip._internal.utils.misc import get_installed_distributions

Neden bu şekilde? Bazen uygulama adı çakışmalarınız olur. Uygulama ad alanından içe aktarmak, sistemde yüklü olanların tam resmini vermez.

Sonuç olarak, pkg_resources.Distributionnesnelerin bir listesini alırsınız . Örnek olarak aşağıdakilere bakın:

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

Bir listesini yapın:

flat_installed_packages = [package.project_name for package in installed_packages]

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

requestsKurulu olup olmadığını kontrol edin :

if 'requests' in flat_installed_packages:
    # Do something

2
Diğer cevapta da belirtildiği gibi hatanın yakalanmamış olması mümkündür. Bu nedenle, bunun kabul edilen cevap olması gerektiğini düşünüyorum.
Jorrick Sleijster

1
Bu yöntem, 'json' gibi paketlerle çalışmaz ( import jsongerçekten çalışırken False döndürür ). İce.nicer yöntemi bu durumda çalışıyor.
mountrix

1
Her nasılsa, benim if "u'requests'" in installed_packages:için çalışması için Güncellenmiş Cevaptan gelen kontrolü kullanmam gerekiyordu . Çıktısı print()bunu macOS python'umda üretir:[..., u'pytz', u'requests', ...]
Buju

1
@ArturBarseghyan Python 2.7.10'dayım (macOS system python) ... aslında kullanmak zorundayım if "requests'"(sondaki tek alıntıya dikkat edin). hiç mantıklı değil.
Buju

1
Bu soruya cevap vermiyor: "'x' paketi yüklü mü?". Kullanmadan bir paket kurmanın birçok yolu vardır pip. Örneğin, kaynaktan bir paket oluşturabilir ve kurabilirsiniz. Bu cevap onları bulamayacak. @ İce.nicer'ın cevabı find_spec()doğru.
Arthur

43

Python 3.3'ten itibaren find_spec () yöntemini kullanabilirsiniz

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
Temiz ve basit, en iyi cevap burada. Bunun daha fazla oylamaya ihtiyacı var.
David Parks

5
Dikkatli ol. Paket adı çizgiler içeriyorsa, nokta kullanmadığınız sürece find_spec () onu bulamaz. Örnek: bulunmazken importlib.util.find_spec('google-cloud-logging')hiçbir şey bulamaz importlib.util.find_spec('google.cloud.logging'). Pip'in gösterdiği resmi ad ve ad noktalarla değil, çizgilerle belirtilmiştir. Kafa karıştırıcı olabilir, bu nedenle dikkatli kullanın.
dwich

27

Çeki terminalden almak istiyorsanız, koşabilirsiniz.

pip3 show package_name

ve hiçbir şey iade edilmezse, paket kurulmaz.

Belki de bu kontrolü otomatikleştirmek istiyorsanız, örneğin eksikse kurabilirsiniz, bash betiğinizde aşağıdakilere sahip olabilirsiniz:

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

Bu harika görünüyor ama benim için her zaman "Yüklü Değil" döndürüyor. Neden?
Elliptica

"$ Pip3 —version" ve "$ pip3 show paket_adı" çıktısını paylaşabilir misiniz, burada paket_ismi yerine istediğiniz paketi koyabilir misiniz?
Ognjen Vukovic

Kabuk ipucu: ifBaşarılı bir komutu doğrudan test etmek için kullanabilirsiniz :if pip3 show package_name 1>/dev/null; then ...
MestreLion

6

Bu cevabın bir uzantısı olarak :

Python 2. * pip show <package_name>için aynı görevi gerçekleştirecektir.

Örneğin pip show numpy, aşağıdakini veya benzerini döndürecektir:

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

Bir komut dosyasından değil, komut satırı kontrolü için harika. Teşekkürler
Jj Rivero

3

Pkg_resources modülünü kurulum araçlarından kullanabilirsiniz. Örneğin:

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 modülü ile bir python paketi arasında bir fark olduğunu unutmayın. Bir paket birden fazla modül içerebilir ve modül adları, paket adıyla eşleşmeyebilir.



1

Bu konuya bazı düşüncelerimi / bulgularımı eklemek istiyorum. Özel yapım bir program için tüm gereksinimleri kontrol eden bir komut dosyası yazıyorum. Python modülleri için de birçok kontrol var.

Küçük bir sorun var

try:
   import ..
except:
   ..

çözüm. Benim durumumda python modüllerinden biri aradı python-nmap, ancak onu import nmapve adların uyuşmadığını gördüğünüz gibi içe aktarıyorsunuz. Bu nedenle, yukarıdaki çözümle yapılan test Yanlış bir sonuç verir ve aynı zamanda modülü isabet halinde içe aktarır, ancak basit bir test / kontrol için çok fazla bellek kullanmaya gerek olmayabilir.

Ben de buldum

import pip
installed_packages = pip.get_installed_distributions()

installed_packagessahip olacak tek paketler olmuştur pip ile yüklü . Sistemimde python modülleri pip freezeüzerinden geri dönüyor , yalnızca manuel olarak yüklediğim (python-nmap) var.40installed_packages1

Soruyla ilgili olmadığını bildiğim başka bir çözüm aşağıda , ancak test işlevini kurulumu gerçekleştirenden ayrı tutmanın iyi bir uygulama olduğunu düşünüyorum , bazıları için yararlı olabilir.

Benim için çalışan çözüm. Bu cevaba dayanmaktadır.İçe aktarmadan bir python modülünün var olup olmadığı nasıl kontrol edilir?

from imp import find_module

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

NOT: Bu çözüm modülü adıyla python-nmapda bulamıyor, nmapbunun yerine kullanmalıyım (birlikte yaşamak kolay) ancak bu durumda modül belleğe herhangi bir şekilde yüklenmeyecek.


0

Betiğinizin eksik paketleri kurmasını ve devam etmesini istiyorsanız, şöyle bir şey yapabilirsiniz ('python-krbV' paketindeki 'krbV' modülü örneğinde):

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

Hızlı bir yol, python komut satırı aracını kullanmaktır . Basitçe yazın import <your module name> Modül eksikse bir hata görürsünüz.

$ 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 ... Uygun bir cevaba en yakın gördüğüm şey, içe aktarmayı denemek için komut satırını kullanmaktı. Ama bundan kaçınmayı bile tercih ederim.

Peki ya 'pip donma | grep pkgname '? Denedim ve iyi çalışıyor. Ayrıca sahip olduğu sürümü ve sürüm kontrolü (yükleme) veya düzenlenebilir (geliştirme) altında mı kurulduğunu gösterir.


0

class myError (istisna): pass #ya da bir şeyler yapın try: import mymodule hariç importError as e: yükselt myError ("hata oluştu")


0

Terminal tipinde

pip show some_package_name

Misal

pip show matplotlib

0

@ İce.nicer yanıtına yorum yapmak istiyorum, ancak yapamam, bu yüzden ... Gözlemlerim, çizgi içeren paketlerin yalnızca @dwich yorumunda belirtildiği gibi noktalarla değil, alt çizgilerle kaydedildiği yönünde.

Örneğin, yaparsınız pip3 install sphinx-rtd-theme, ancak:

  • importlib.util.find_spec(sphinx_rtd_theme) bir Nesne döndürür
  • importlib.util.find_spec(sphinx-rtd-theme) Hiçbiri döndürür
  • importlib.util.find_spec(sphinx.rtd.theme) ModuleNotFoundError'ı yükseltir

Üstelik bazı isimler tamamen değiştirildi. Örneğin, yaparsınız pip3 install pyyamlancak basitçeyaml

Python3.8 kullanıyorum


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

-1

Git seçeneği # 2. Eğer ImportErroratılır, daha sonra paket yüklü değil (ya da değil de sys.path).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.