I want to get a list from all imports of a (selfwritten) module and fetch them via PIP programmatically. Is there a way to do this?
I thought of analysing the file via open(model.py) extract the import statements and then subprocess PIP, but is there a better way?
EDIT:
This helps out with PIP:
http://blog.ducky.io/python/2013/08/22/calling-pip-programmatically/
There are two options that I know of.
pigar
pipreqs
Both will pull imports from your project and give you a requirements.txt file that you can use with pip.
You could wrap it in a try/except condition.
something like:
import pip
while True:
try:
import mymodule
break
except ImportError as e:
dependency = str(e).split(" ")[-1]
if dependency == 'mymodule':
break
pip.main(['install', dependency])
my thinking:
try to import - if you don't have the dependencies installed you should raise an ImportError
if it fails the last word of the error message should be the name of the module you need, install it using pip as suggested in the page you linked.
you could also get an ImportError if your module doesn't exist - so we test for that and break
I can imagine a problem, depending on the pip module (which I haven't used) if a module has a different import name to pip name, eg MySQLdb, which is installed via $pip install MySQL-python
Depending on the answer from Rob, I came to the following solution:
def satisfy_dependencies(path_to_dir):
# Generate requirements.txt using pipreqs and then use pip to fetch the requirements
proc = Popen(["pipreqs", path_to_dir, "--savepath", os.path.join(path_to_dir, "requirements.txt"), "--force"])
while proc.poll() is None:
time.sleep(0.1)
if os.path.exists(os.path.join(path_to_dir, "requirements.txt")):
pip = Popen(["pip", "install", "-r", os.path.join(path_to_dir, "requirements.txt")])
while pip.poll() is None:
time.sleep(0.1)
os.remove(os.path.join(path_to_dir, "requirements.txt"))
Much sub processing but did the job in my case.
I'll be back.
TLDR; I need simple a Python call given a package name (e.g., 'make') to see if it's installed; if not, install it (I can do the latter part).
Problem:
So there are a few code examples given in http://yum.baseurl.org/wiki/YumCodeSnippets, but other than kludging around inside ipython and guessing at what each method does, there doesn't appear to be any actual documentation for the Python API for yum. It's apparently all tribal knowledge.
[edit] Apparently I just accidentally discovered the API documentation (after receiving an acceptable answer, of course). It's not linked from the main page, but here it is for future reference: http://yum.baseurl.org/api/yum/
What I need to do:
I have a deployment configuration script that relies on other system packages (make, gcc, etc.). I know I can install them like this: http://yum.baseurl.org/wiki/YumCodeSnippet/SimplestTransaction but I'd like to have the option to query if they're already installed before doing so, so I can have the additional option of simply failing if the packages aren't present instead of forcing installation. What's the proper call to do this (or better, has anyone actually bothered to properly document the API outside of code samples?)
I've never touched Python prior to this project, and I'm really liking it, but... some of the module documentation is more elusive than unicorn-riding leprechauns.
import yum
yb = yum.YumBase()
if yb.rpmdb.searchNevra(name='make'):
print "installed"
else:
print "not installed"
You could run 'which' on the subsystem to see if the system has the binaries you are looking for:
import os
os.system("which gcc")
os.system("which obscurepackagenotgoingtobefound")
For anyone who stumbles across this post later, here's what I came up with. Note that "testing" and "skip_install" are flags that I parse from the script invocation.
print "Checking for prerequisites (Apache, PHP + PHP development, autoconf, make, gcc)"
prereqs = list("httpd", "php", "php-devel", "autoconf", "make", "gcc")
missing_packages = set()
for package in prereqs:
print "Checking for {0}... ".format([package]),
# Search the RPM database to check if the package is installed
res = yb.rpmdb.searchNevra(name=package)
if res:
for pkg in res:
print pkg, "installed!"
else:
missing_packages.add(package)
print package, "not installed!"
# Install the package if missing
if not skip_install:
if testing:
print "TEST- mock install ", package
else:
try:
yb.install(name=package)
except yum.Errors.InstallError, err:
print >> sys.stderr, "Failed during install of {0} package!".format(package)
print >> sys.stderr, str(err)
sys.exit(1)
# Done processing all package requirements, resolve dependencies and finalize transaction
if len(missing_packages) > 0:
if skip_install:
# Package not installed and set to not install, so fail
print >> sys.stderr, "Please install the {0} packages and try again.".format(
",".join(str(name) for name in missing_packages))
sys.exit(1)
else:
if testing:
print "TEST- mock resolve deps and process transaction"
else:
yb.resolveDeps()
yb.processTransaction()
import yum
yb = yum.YumBase()
yb.isPackageInstalled('make')
Is there an elegant and more Python-like way to check if a package is installed on Debian?
In a bash script, I'd do:
dpkg -s packagename | grep Status
Suggestions to do the same in a Python script?
This is a pythonic way:
import apt
cache = apt.Cache()
if cache['package-name'].is_installed:
print "YES it's installed"
else:
print "NO it's NOT installed"
A slightly nicer, hopefully idiomatic version of your bash example:
import os, subprocess
devnull = open(os.devnull,"w")
retval = subprocess.call(["dpkg","-s","coreutils"],stdout=devnull,stderr=subprocess.STDOUT)
devnull.close()
if retval != 0:
print "Package coreutils not installed."
If you are checking for the existence of a package that installs a Python module, you can test for this from within a dependent Python script - try to import it and see if you get an exception:
import sys
try:
import maybe
except ImportError:
print "Sorry, must install the maybe package to run this program."
sys.exit(1)
This is some code that would give you a neat way to display if the package is installed or not (without triggering a messy error message on the screen). This works in Python 3 only, though.
import apt
cache = apt.Cache()
cache.open()
response = "Package Installed."
try:
cache['notapkg'].is_installed
except KeyError:
response = "Package Not Installed."
print(response)
Have a look at commands. It's very useful for running things on the command line and getting the status.
Otherwise, I'm sure there is some library that will let you interact with apt. python-apt might work but it's a bit raw. Just capturing the command line seems easier.
I needed a cross-platform compatible solution so I ended up using which.
import subprocess
retval = subprocess.call(["which", "packagename"])
if retval != 0:
print("Packagename not installed!")
Although it's not as pythonic as the above answers it does work on most platforms.
Inspired by the previous answers, this works nicely for both Python 2 and Python 3 and avoids try/catch for the key error:
import apt
package = 'foo' # insert your package name here
cache = apt.Cache()
package_installed = False
if package in cache:
package_installed = cache[package].is_installed
I had the same doubt. Searched every corner in the Internet but couldn't find it.
But finally after some Experiments I DID IT!!.
Code:
import os
packagename = "figlet" # Type in your package name
os.system("dpkg -s "+packagename" | grep Status")
To type in any terminal using python codes:
Code:
import os
os.system("YOUR TERMINAL COMMAND HERE")
What's a good way to check if a package is installed while within a Python script? I know it's easy from the interpreter, but I need to do it within a script.
I guess I could check if there's a directory on the system that's created during the installation, but I feel like there's a better way. I'm trying to make sure the Skype4Py package is installed, and if not I'll install it.
My ideas for accomplishing the check
check for a directory in the typical install path
try to import the package and if an exception is throw, then install package
If you mean a python script, just do something like this:
Python 3.3+ use sys.modules and 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.
As of Python 3.3, you can use the find_spec() method
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")
Updated answer
A better way of doing this is:
import subprocess
import sys
reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'])
installed_packages = [r.decode().split('==')[0] for r in reqs.split()]
The result:
print(installed_packages)
[
"Django",
"six",
"requests",
]
Check if requests is installed:
if 'requests' in installed_packages:
# Do something
Why this way? Sometimes you have app name collisions. Importing from the app namespace doesn't give you the full picture of what's installed on the system.
Note, that proposed solution works:
When using pip to install from PyPI or from any other alternative source (like pip install http://some.site/package-name.zip or any other archive type).
When installing manually using python setup.py install.
When installing from system repositories, like sudo apt install python-requests.
Cases when it might not work:
When installing in development mode, like python setup.py develop.
When installing in development mode, like pip install -e /path/to/package/source/.
Old answer
A better way of doing this is:
import pip
installed_packages = pip.get_installed_distributions()
For pip>=10.x use:
from pip._internal.utils.misc import get_installed_distributions
Why this way? Sometimes you have app name collisions. Importing from the app namespace doesn't give you the full picture of what's installed on the system.
As a result, you get a list of pkg_resources.Distribution objects. See the following as an example:
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)",
]
Make a list of it:
flat_installed_packages = [package.project_name for package in installed_packages]
[
"Django",
"six",
"requests",
]
Check if requests is installed:
if 'requests' in flat_installed_packages:
# Do something
If you want to have the check from the terminal, you can run
pip3 show package_name
and if nothing is returned, the package is not installed.
If perhaps you want to automate this check, so that for example you can install it if missing, you can have the following in your bash script:
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
Open your command prompt type
pip3 list
As an extension of this answer:
For Python 2.*, pip show <package_name> will perform the same task.
For example pip show numpy will return the following or alike:
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
In the Terminal type
pip show some_package_name
Example
pip show matplotlib
You can use the pkg_resources module from setuptools. For example:
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)
Note that there is a difference between python module and a python package. A package can contain multiple modules and module's names might not match the package name.
if pip list | grep -q \^'PACKAGENAME\s'
# installed ...
else
# not installed ...
fi
You can use this:
class myError(exception):
pass # Or do some thing like this.
try:
import mymodule
except ImportError as e:
raise myError("error was occurred")
Method 1
to search weather a package exists or not use pip3 list command
#**pip3 list** will display all the packages and **grep** command will search for a particular package
pip3 list | grep your_package_name_here
Method 2
You can use ImportError
try:
import your_package_name
except ImportError as error:
print(error,':( not found')
Method 3
!pip install your_package_name
import your_package_name
...
...
I'd like to add some thoughts/findings of mine to this topic.
I'm writing a script that checks all requirements for a custom made program. There are many checks with python modules too.
There's a little issue with the
try:
import ..
except:
..
solution.
In my case one of the python modules called python-nmap, but you import it with import nmap and as you see the names mismatch. Therefore the test with the above solution returns a False result, and it also imports the module on hit, but maybe no need to use a lot of memory for a simple test/check.
I also found that
import pip
installed_packages = pip.get_installed_distributions()
installed_packages will have only the packages has been installed with pip.
On my system pip freeze returns over 40 python modules, while installed_packages has only 1, the one I installed manually (python-nmap).
Another solution below that I know it may not relevant to the question, but I think it's a good practice to keep the test function separate from the one that performs the install it might be useful for some.
The solution that worked for me. It based on this answer How to check if a python module exists without importing it
from imp import find_module
def checkPythonmod(mod):
try:
op = find_module(mod)
return True
except ImportError:
return False
NOTE: this solution can't find the module by the name python-nmap too, I have to use nmap instead (easy to live with) but in this case the module won't be loaded to the memory whatsoever.
I would like to comment to #ice.nicer reply but I cannot, so ...
My observations is that packages with dashes are saved with underscores, not only with dots as pointed out by #dwich comment
For example, you do pip3 install sphinx-rtd-theme, but:
importlib.util.find_spec(sphinx_rtd_theme) returns an Object
importlib.util.find_spec(sphinx-rtd-theme) returns None
importlib.util.find_spec(sphinx.rtd.theme) raises ModuleNotFoundError
Moreover, some names are totally changed.
For example, you do pip3 install pyyaml but it is saved simply as yaml
I am using python3.8
If you'd like your script to install missing packages and continue, you could do something like this (on example of 'krbV' module in 'python-krbV' package):
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))
A quick way is to use python command line tool.
Simply type import <your module name>
You see an error if module is missing.
$ 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
$
Hmmm ... the closest I saw to a convenient answer was using the command line to try the import. But I prefer to even avoid that.
How about 'pip freeze | grep pkgname'? I tried it and it works well. It also shows you the version it has and whether it is installed under version control (install) or editable (develop).
I've always used pylibcheck to check if a lib is installed or not, simply download it by doing pip install pylibcheck and the could could be like this
import pylibcheck
if not pylibcheck.checkPackage("mypackage"):
#not installed
it also supports tuples and lists so you can check multiple packages and if they are installed or not
import pylibcheck
packages = ["package1", "package2", "package3"]
if pylibcheck.checkPackage(packages):
#not installed
you can also install libs with it if you want to do that, recommend you check the official pypi
The top voted solution which uses techniques like importlib.util.find_spec and sys.modules and catching import exceptions works for most packages but fails in some edge cases (such as the beautifulsoup package) where the package name used in imports is somewhat different (bs4 in this case) than the one used in setup file configuration. For these edge cases, this solution doesn't work unless you pass the package name used in imports instead of the one used in requirements.txt or pip installations.
For my use case, I needed to write a package checker that checks installed packages based on requirements.txt, so this solution didn't work. What I ended up using was subprocess.check to call the pip module explicitly to check for the package installation:
import subprocess
for pkg in packages:
try:
subprocess.check_output('py -m pip show ' + pkg)
except subprocess.CalledProcessError as ex:
not_found.append(pkg)
It's a bit slower than the other methods but more reliable and handles the edge cases.
Go option #2. If ImportError is thrown, then the package is not installed (or not in sys.path).
Is there any chance to use the snippets given below? When I run this code, it returns "module pandas is not installed"
a = "pandas"
try:
import a
print("module ",a," is installed")
except ModuleNotFoundError:
print("module ",a," is not installed")
But when I run the code given below:
try:
import pandas
print("module is installed")
except ModuleNotFoundError:
print("module is not installed")
It returns "module pandas is installed".
What is the difference between them?