0

How can I check is some package is installed in my system. My system is Linux, but even better if it could works in other OSs. I mean OS specific package (like could be *.rpm or *.deb).

Is there any python module or script that could do it?

jww
  • 97,681
  • 90
  • 411
  • 885
John Lapoya
  • 582
  • 1
  • 8
  • 21
  • possible duplicate of [Check if a program exists from a python script](http://stackoverflow.com/questions/11210104/check-if-a-program-exists-from-a-python-script) – dwitvliet Jul 24 '14 at 18:03
  • Take a look at [python apt package/module](http://apt.alioth.debian.org/python-apt-doc/) – RanRag Jul 24 '14 at 18:03
  • When you say *"package"*, do you mean a packaged Python module, or an OS-specific package (like *.rpm or *.deb)? – Lukas Graf Jul 24 '14 at 18:12
  • @LukasGraf: I think he means neither, but rather a Python package (as in a directory with `__init__.py` and some submodules or subpackages, loosely speaking). – abarnert Jul 24 '14 at 18:13
  • One more possible meaning, of course, is the `pkgconfig` notion of packages, which is the only thing that could make this make sense as a sort-of-linux-specific but not distro-specific question… but I'm willing to bet that's not what he's asking. – abarnert Jul 24 '14 at 18:14
  • @LukasGraf, I mean an OS specific package, sorry if my question was not clear at all – John Lapoya Jul 24 '14 at 18:16
  • It's not just not clear, it's completely misleading. What is a "module" in .deb? – abarnert Jul 24 '14 at 18:28

2 Answers2

3

The word "package" has a half-dozen similar but incompatible meanings, but the fact that you said "package or module" implies you specifically want to know about Python packages and modules, as in the things you can import.

In which case, the way to test it is to import them.

Manually, do this:

$ python
>>> import foo
ImportError: No module named foo

Well, foo isn't installed.

Programmatically:

try:
    import foo
except ImportError:
    # do whatever you wanted if foo is missing

Note that this doesn't actually tell you foo is missing, just that it couldn't be imported. In a simple "test whether you have this" script, that's generally what you want to actually check for. But what if you really want to check "is installed (even if broken)"?

In recent Python (I think 3.4+), the ImportError will have additional information in it that you can access—name for the name you were trying to import, path if it was found, etc. However, this is one of those cases where EAFP may not be better than LBYL. You can use importlib to search for the module without trying to import it, like this:

spec = importlib.util.find_spec('foo')

What if you're using an older Python? There are similar features going back to 3.2, but not quite as nice, and if you're using 2.7, there's really nothing worth using, because the import machinery wasn't exposed very well.

For that case (and many, many other cool things related to package installation), use setuptools—which isn't in the stdlib, but a huge number of third-party packages depend on it (until recently it was the cornerstone of Python package installation, even if unofficially):

pkg_resources.get_distribution('foo')

However, that looks for a distutils/setuptools/PyPI package, not a Python module or package. There's a lot of overlap there, but they're not exactly the same thing. For a simple example, when you pip install more-itertools, you get the more-itertools PyPI package, which installs the more_itertools Python package into your site-packages.

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • To check for availability of Python modules, `pkg_resources.get_distribution('foo')` and catching `DistributionNotFound` should be used - catching `ImportError`s [may hide circular dependencies](http://do3.cc/blog/2010/08/20/do-not-catch-import-errors,-use-pkg_resources/). – Lukas Graf Jul 24 '14 at 18:13
  • @LukasGraf: `import` can have other problems too, but for quick&dirty checking, it tells you whether you can import the module or not (a simple test script isn't going to have circular dependencies—unless, of course, the module itself does, in which case you can't import it, so that's the right answer). `pkg_resources` is part of `setuptools`, and one of those "fancier things" I already mentioned, but maybe I should expand it in the answer. – abarnert Jul 24 '14 at 18:16
  • I agree, it's a more advanced detail - hence still +1 ;-) But it is the proper API, and it does answer the exact question the OP asked: Is module XY installed? If it is usuable is a sligtly different question, and one might want to let that error surface. – Lukas Graf Jul 24 '14 at 18:20
  • @LukasGraf: Well, it's the proper API for packages installed by `setuptools`; it's a hacky-and-not-official-but-thoroughly-reliable API for packages installed in any other way (except `distribute` or native 3.4+ `pip`). But, more importantly, it's the API for `distutils` packages, not for modules and packages. Except in the case where a `distutils` package contains exactly one module or package with the same name as itself, you're getting the wrong answer. – abarnert Jul 24 '14 at 18:28
  • Yes, my phrasing *"availability of Python modules"* was incorrect - I should have said "setuptools based distributions". So if you're interested in the `ImageOps` module you obviously would need to check for the `PIL` distribution (or `Pillow` for that matter). – Lukas Graf Jul 24 '14 at 18:52
  • @LukasGraf: Of course it turns out that by "modules and packages" he meant _neither_ "Python modules and packages" nor "`distutils`/PyPA distributions", so we're _both_ talking about the wrong thing here. :) – abarnert Jul 25 '14 at 21:03
3

To find out whether you've installed a .deb, .rpm, etc. package, you need to use the appropriate tools for your packaging system.

APT has a Python wrapper named python-apt in Debian, or just apt at PyPI.

RPM has a whole slew of Python tools—in fact, most of Redhat's installer ecosystem is built on Python, and you should already have the rpm module installed. Read Programming RPM with Python (or, better, search for a newer version…) before looking for a high-level wrapper, so you understand what you're actually doing; it's only a couple lines of code even with the low-level interface.

As far as I know, nobody has wrapped these up in a universal tool for every packaging format and database that any linux distro has ever used (and, even if they had, that wouldn't do you much good on linux systems that don't use a packaging system). But if you just want to handle a handful of popular systems, python-apt and either Redhat's own tools or search PyPI for RPM, and that will cover almost everything you care about.

Alternatively, pkg-config is the closest thing to a universal notion of "packages installed on this system". Every linux system will have it (and most other non-Windows systems), but not every package registers with pkg-config. Still, if this is what you're looking for, pkgconfig is the Python answer.

abarnert
  • 354,177
  • 51
  • 601
  • 671