GeoDjango GEOSException error - python

Trying to install a GeoDjango on my machine. I'm really new to Python and being brought into a project that has been a very tricky install for the other team members. I installed Python 2.7 and GEOS using brew, and running PSQL 9.2.4 but keep getting this error when I try to get the webserver running:
__import__(name)
File "/Users/armynante/Desktop/uclass-files/uclass-env/lib/python2.7/site
packages/django/contrib/gis/geometry/backend/geos.py", line 1, in <module>
from django.contrib.gis.geos import (
File "/Users/armynante/Desktop/uclass-files/uclass-env/lib/python2.7/site
packages/django/contrib/gis/geos/__init__.py", line 6, in <module>
from django.contrib.gis.geos.geometry import GEOSGeometry, wkt_regex, hex_regex
File "/Users/armynante/Desktop/uclass-files/uclass-env/lib/python2.7/site
packages/django/contrib/gis/geos/geometry.py", line 14, in <module>
from django.contrib.gis.geos.coordseq import GEOSCoordSeq
File "/Users/armynante/Desktop/uclass-files/uclass-env/lib/python2.7/site-
packages/django/contrib/gis/geos/coordseq.py", line 9, in <module>
from django.contrib.gis.geos.libgeos import CS_PTR
File "/Users/armynante/Desktop/uclass-files/uclass-env/lib/python2.7/site-
packages/django/contrib/gis/geos/libgeos.py", line 119, in <module>
_verinfo = geos_version_info()
File "/Users/armynante/Desktop/uclass-files/uclass-env/lib/python2.7/site
packages/django/contrib/gis/geos/libgeos.py", line 115, in geos_version_info
if not m: raise GEOSException('Could not parse version info string "%s"' % ver)
django.contrib.gis.geos.error.GEOSException: Could not parse version info string
"3.4.2-CAPI-1.8.2 r3921"
Cant seem to find anything relevant to this trace on SO or the web. I think it might be a regex failure? I'm currently trying to reinstall PSQL and GEOS to see if I can get it running.
Here is my requirements file:
django==1.4
psycopg2==2.4.4
py-bcrypt==0.4
python-memcached==1.48
south==0.7.3
# Debug Tools
sqlparse==0.1.3
django-debug-toolbar==0.9.1
django-devserver==0.3.1
# Deployment
fabric==1.4
# AWS
# boto==2.1.1
django-storages==1.1.4
django-ses==0.4.1
# ECL
http://packages.elmcitylabs.com/ecl_django-0.5.3.tar.gz#ecl_django
http://packages.elmcitylabs.com/ecl_google-0.2.14.tar.gz#ecl_google
# https://packages.elmcitylabs.com/ecl_tools-0.3.7.tar.gz#ecl_tools
# https://packages.elmcitylabs.com/chargemaster-0.2.19.tar.gz
# https://packages.elmcitylabs.com/ecl_facebook-0.3.12.tar.gz#ecl_facebook
# https://packages.elmcitylabs.com/ecl_twitter-0.3.3.tar.gz#ecl_twitter
# Search
#https://github.com/elmcitylabs/django-haystack/tarball/issue-522#django-haystack
-e git+https://github.com/toastdriven/django-haystack.git#egg=django-haystack
pysolr==2.1.0-beta
# whoosh==2.3.2
# Misc
# PIL
# django-shorturls==1.0.1
# suds==0.4
django-mptt
sorl-thumbnail
stripe
pytz==2013b

This is my solution (obviously it is ugly, like my English, but works).
The problem is that the versions string has an white space unwanted in the RegEx.
The error says:
GEOSException: Could not parse version info string "3.4.2-CAPI-1.8.2 r3921"
And the geos_version_info warns:
Regular expression should be able to parse version strings such as
'3.0.0rc4-CAPI-1.3.3', '3.0.0-CAPI-1.4.1' or '3.4.0dev-CAPI-1.8.0'
Edit this file: site-packages/django/contrib/gis/geos/libgeos.py
Look for the function: geos_version_info
And change this line:
ver = geos_version().decode()
With this line:
ver = geos_version().decode().split(' ')[0]
There is also another problem, where there is a whitespace at the end but no more information is provided. Such version also doesn't match version regular expression, so strip()-ping the version may be expected behaviour as a quick fix. In my example it was: '3.8.0-CAPI-1.13.1 '

In the latest GEOS install, the above answer didn't work... but was close to the problem.
I changed the regex right above the geos_version_info():
from:
version_regex = re.compile(r'^(?P<version>(?P<major>\d+)\.(?P<minor>\d+)\.(?P<subminor>\d+))((rc(?P<release_candidate>\d+))|dev)?-CAPI-(?P<capi_version>\d+\.\d+\.\d+)$')
to be:
version_regex = re.compile(r'^(?P<version>(?P<major>\d+)\.(?P<minor>\d+)\.(?P<subminor>\d+))((rc(?P<release_candidate>\d+))|dev)?-CAPI-(?P<capi_version>\d+\.\d+\.\d+).*$')
Notice the .* added to the end of the regex.

I think this is broken again. A recent upgrade on our FreeBSD server led to this error:
django.contrib.gis.geos.error.GEOSException: Could not parse version info string "3.6.2-CAPI-1.10.2 4d2925d6"
Looks like the regex in Django's libgeos.py needs to be updated again to account for this different syntax. Nachopro's solution still serves as a workaround.

It appears that this has been fixed in Django as of last March or so. See also Django bug 20036. So upgrading to Django 1.5.4 will solve the problem.

For those folks who don't have 3.6.1 previously installed:
brew unlink geos
Install 3.6.1 with brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/145b22e8330e094ee148861e72e26c03e73d34a1/Formula/geos.rb.
brew info geos should show 3.6.1 starred:

Brew just released geos 3.8.0 that of course breaks Django 1.11 again.
The previous version, 3.7.3, was oh so very helpfully cleared by the all new all automatic cleanup now running on upgrades, so no brew switch geos 3.7.3 for me.
I ended up using this post to understand how to find the previous version number and commit hash:
cd $( brew --prefix )/Homebrew/Library/Taps/homebrew/homebrew-core
git log -- Formula/geos.rb | less
# find the version you need in the file, copy its hash
brew unlink geos
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/<yourcommithash>/Formula/geos.rb
After all this, the download for geos 3.7.3 fails SHA256 checksum validation for some reason... so I ended up trying 3.7.2, that actually worked.
For now the command to reinstall 3.7.2 on Catalina is:
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/823b700ab61eeec57f34d50be2cc34a285fb5abc/Formula/geos.rb

If one cannot for any reason edit the site packages themselves, this ugly hack did it for me without having to act on the environment itself:
try:
__import__('django.contrib.gis.geos.libgeos', fromlist=['version_regex'])
except Exception as e:
import re
att = __import__('django.contrib.gis.geos.libgeos', fromlist=['version_regex'])
setattr(att, 'version_regex', re.compile(
'^(?P<version>(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<subminor>\\d+))((rc(?P<release_candidate>\\d+))|dev)?-CAPI-(?P<capi_version>\\d+\\.\\d+\\.\\d+)( r\\d+)?( \\w+)?.*$'))
assert str(type(e)) == "<class 'django.contrib.gis.geos.error.GEOSException'>", str(e)
It is based on JayCrossler's answer.
Update
The above executes code found within the django.contrib.gis.geos.__init__.py module, which already tries to use the problematic part, rendering the above solution unusable (for python 2.7+). This can be worked around as:
import sys
try:
import django.contrib.gis.geos.libgeos
except Exception as e:
import re
setattr(sys.modules['django.contrib.gis.geos.libgeos'],'version_regex', re.compile(
'^(?P<version>(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<subminor>\\d+))((rc(?P<release_candidate>\\d+))|dev)?-CAPI-(?P<capi_version>\\d+\\.\\d+\\.\\d+)( r\\d+)?( \\w+)?.*$'))
assert str(type(e)) == "<class 'django.contrib.gis.geos.error.GEOSException'>", str(e)
Where basically we are acting directly on the module in sys.modules instead of trying to get it from another import that will fail.

This can be fixed by trying the following,
brew switch geos 3.6.1

I fixed the issue by installing PostGIS with Postgres using https://postgresapp.com/downloads.html.
Install PostGIS (2.2): brew install postgis
To unlink geos if version is higher than 3.6.1: brew unlink geos
Install Geos (3.6.1): brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/145b22e8330e094ee148861e72e26c03e73d34a1/Formula/geos.rb
Switch geos version(latest version is 3.7.2 which is not supported by Django 1.11.3): brew switch geos 3.6.1
Login to database and create postgis extensions: CREATE EXTENSION postgis;
Test postgis extension: SELECT ST_Distance('LINESTRING(-122.33 47.606, 0.0 51.5)'::geography, 'POINT(-21.96 64.15)'::geography);
Check postgis version: SELECT PostGIS_full_version();

Related

PyLaTeX: pylatex.errors.CompilerError: No LaTex compiler was found

I am trying to run the exact code from here to get an example of pylatex working.
In the directory that I am working in, I have copied and pasted from the link:
from pylatex import Document, Section, Subsection, Command
from pylatex.utils import italic, NoEscape
import pdflatex
def fill_document(doc):
"""Add a section, a subsection and some text to the document.
:param doc: the document
:type doc: :class:`pylatex.document.Document` instance
"""
with doc.create(Section('A section')):
doc.append('Some regular text and some ')
doc.append(italic('italic text. '))
with doc.create(Subsection('A subsection')):
doc.append('Also some crazy characters: $&#{}')
if __name__ == '__main__':
# Basic document
doc = Document('basic')
fill_document(doc)
doc.generate_pdf(clean_tex=False,compiler='pdflatex')
doc.generate_tex()
# Document with `\maketitle` command activated
doc = Document()
doc.preamble.append(Command('title', 'Awesome Title'))
doc.preamble.append(Command('author', 'Anonymous author'))
doc.preamble.append(Command('date', NoEscape(r'\today')))
doc.append(NoEscape(r'\maketitle'))
fill_document(doc)
doc.generate_pdf('basic_maketitle', clean_tex=False)
# Add stuff to the document
with doc.create(Section('A second section')):
doc.append('Some text.')
doc.generate_pdf('basic_maketitle2', clean_tex=False)
tex = doc.dumps() # The document as string in LaTeX syntax
I consistently get the error:
Traceback (most recent call last):
File "test.py", line 26, in <module>
doc.generate_pdf(clean_tex=False,compiler='pdflatex')
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.7/site-packages/pylatex/document.py", line 280, in generate_pdf
'Either specify a LaTex compiler ' +
pylatex.errors.CompilerError: No LaTex compiler was found
You can see some of the things I've tried based on other people's suggestions:
1. if I just open a python console in this directory, and type:
from pylatex import Document, Section, Subsection, Command
from pylatex.utils import italic, NoEscape
import pdflatex
there are no errors, implying importing was successful.
I saw another recommendation that perl must be installed, which it is:
localhost:test1$ perl --version : returns info about perl
I've specified the compiler as was suggested elsewhere on StackOverflow: 'doc.generate_pdf(clean_tex=False,compiler='pdflatex')'
What else can I do? The ultimate aim is I have generated strings and an image with python, and I want to put them both into a PDF and format, in case there is a better alternative that anyone can suggest. P.s. I'm aware of the tex stack exchange, but I specifically need a way for latex to interact with python, which is why I asked here.
Apparantly you'll need to run these two apt-get dependencies
sudo apt-get install latexmk
sudo apt-get install -y texlive-latex-extra
also install pdflatex with pip
pip install pdflatex
then use
doc.generate_pdf(compiler='pdflatex')
For me, on CentOS 8, I had to run:
pip install pylatex
sudo dnf install texlive
sudo dnf install texlive-lastpage
Then it worked for me.
I had this same error and my problem was that I had forgotten to add pdflatex (through MiKTex) to my environment path in Windows. My code worked after reloading my terminal. I have not installed Perl by the way.

Python GEOS ImportError

I'm getting this error:
ImportError: Could not find the GEOS library (tried ""geos_c"", ""libgeos_c-1"").
Try setting GEOS_LIBRARY_PATH in your settings
when I run:
from django.contrib.gis.geos import *
pnt=GEOSGeometry('POINT(23 5)')
print(pnt)
I added GEOS_LIBRARY_PATH = 'C:/Python34/Lib/site-packages/osgeo/geos_c.dll'
in C:\Python34\Lib\site-packages\django\conf\project_template\project_name\settings.py
But still Im getting the same error. How to solve this?
I don't know what is the most correct way to use with Windows, you can try to find solution here, but for ubuntu command:
sudo apt-get install binutils libproj-dev gdal-bin
solved the problem.
P.S. From dock:
The setting must be the full path to the C shared library; in other words you want to use libgeos_c.so, not libgeos.so.
Extension of the library must be *_c.so
Are You sure path is correct? This is My path:
GEOS_LIBRARY_PATH = 'c:\\Program Files\\PostgreSQL\\9.1\\bin\\libgeos_c-1'
You need GEOS from PostgreSQL.

Import error in twilio

I am having the same problem as this thread regarding twilio-python:
twilio.rest missing from twilio python module version 2.0.8?
However I have the same problem but I have 3.3.3 installed. I still get "No module named rest" when trying to import twilio.rest.
Loading the library from stand alone python script works. So I know that pip installing the package worked.
from twilio.rest import TwilioRestClient
def main():
account = "xxxxxxxxxxxxxxxx"
token = "xxxxxxxxxxxxxxxx"
client = TwilioRestClient(account, token)
call = client.calls.create(to="+12223344",
from_="+12223344",
url="http://ironblanket.herokuapp.com/",
method="GET")
if __name__ == "__main__":
main()
but this does not work:
from twilio.rest import TwilioRestClient
def home(request):
client = TwilioRestClient(account, token)
Do you have any idea what I can try next?
I named a python file in my project twilio.py. Since that file was loaded first, then subsequent calls to load twilio would reference that file instead of the twilio library.
TLDR: just don't name your python file twilio.py
Check which versions of pip and python you are running with this command:
which -a python
which -a pip
pip needs to install to a path that your Python executable can read from. Sometimes there will be more than one version of pip like pip-2.5, pip-2.7 etc. You can find all of them by running compgen -c | grep pip. There can also be more than one version of Python, especially if you have Macports or brew or multiple versions of Python installed.
Check which version of the twilio module is installed by running this command:
$ pip freeze | grep twilio # Or pip-2.7 freeze etc.
The output should be twilio==3.3.3.
I hope that helps - please leave a comment if you have more questions.
This Worked For me : (Windows)
Python librarys are in G:\Python\Lib
(Python is installed at G:, it might be different for you)
Download Twilio from github at paste the library at >> G:\Python\Lib <<
import problem gone :)
I had the same issue and it drove me crazy. Finally I figured it out. When you get the error:
AttributeError: module 'twilio' has no attribute 'version'
Look 2 lines above and the error is telling you where it expects to find the twilio file. So I moved it from where it was to where it was asking it to be.
Installed to:
c:\users\rhuds\appdata\local\programs\python\python37-32\lib\site-packages
Moved it to:
Traceback (most recent call last):
File "", line 1, in
import twilio
File "C:\Users\rhuds\AppData\Local\Programs\Python\Python37-32\twilio.py", line 2, in
Now I can import twilio. Besides that, the only other thing I did was uninstall old versions of Python, but I don't think that really mattered.

How can I get sqlite working on a shared hosting server?

I'm trying to run a python script using python 2.6.4. The hosting company has 2.4 installed so I compiled my own 2.6.4 on a similar server and then moved the files over into ~/opt/python. that part seems to be working fine.
anyhow, when I run the script below, I am getting ImportError: No module named _sqlite3 and I'm not sure what to do to fix this.
Most online threads mention that sqlite / sqlite3 is included in python 2.6 - so I'm not sure why this isn't working.
-jailshell-3.2$ ./pyDropboxValues.py
Traceback (most recent call last):
File "./pyDropboxValues.py", line 21, in
import sqlite3
File "/home/myAccount/opt/lib/python2.6/sqlite3/__init__.py", line 24, in
from dbapi2 import *
File "/home/myAccount/opt/lib/python2.6/sqlite3/dbapi2.py", line 27, in
from _sqlite3 import *
ImportError: No module named _sqlite3
I think I have everything set up right as far as the directory structure.
-jailshell-3.2$ find `pwd` -type d
/home/myAccount/opt
/home/myAccount/opt/bin
/home/myAccount/opt/include
/home/myAccount/opt/include/python2.6
/home/myAccount/opt/lib
/home/myAccount/opt/lib/python2.6
/home/myAccount/opt/lib/python2.6/distutils
/home/myAccount/opt/lib/python2.6/distutils/command
/home/myAccount/opt/lib/python2.6/distutils/tests
/home/myAccount/opt/lib/python2.6/compiler
/home/myAccount/opt/lib/python2.6/test
/home/myAccount/opt/lib/python2.6/test/decimaltestdata
/home/myAccount/opt/lib/python2.6/config
/home/myAccount/opt/lib/python2.6/json
/home/myAccount/opt/lib/python2.6/json/tests
/home/myAccount/opt/lib/python2.6/email
/home/myAccount/opt/lib/python2.6/email/test
/home/myAccount/opt/lib/python2.6/email/test/data
/home/myAccount/opt/lib/python2.6/email/mime
/home/myAccount/opt/lib/python2.6/lib2to3
/home/myAccount/opt/lib/python2.6/lib2to3/pgen2
/home/myAccount/opt/lib/python2.6/lib2to3/fixes
/home/myAccount/opt/lib/python2.6/lib2to3/tests
/home/myAccount/opt/lib/python2.6/xml
/home/myAccount/opt/lib/python2.6/xml/parsers
/home/myAccount/opt/lib/python2.6/xml/sax
/home/myAccount/opt/lib/python2.6/xml/etree
/home/myAccount/opt/lib/python2.6/xml/dom
/home/myAccount/opt/lib/python2.6/site-packages
/home/myAccount/opt/lib/python2.6/logging
/home/myAccount/opt/lib/python2.6/lib-dynload
/home/myAccount/opt/lib/python2.6/sqlite3
/home/myAccount/opt/lib/python2.6/sqlite3/test
/home/myAccount/opt/lib/python2.6/encodings
/home/myAccount/opt/lib/python2.6/wsgiref
/home/myAccount/opt/lib/python2.6/multiprocessing
/home/myAccount/opt/lib/python2.6/multiprocessing/dummy
/home/myAccount/opt/lib/python2.6/curses
/home/myAccount/opt/lib/python2.6/bsddb
/home/myAccount/opt/lib/python2.6/bsddb/test
/home/myAccount/opt/lib/python2.6/idlelib
/home/myAccount/opt/lib/python2.6/idlelib/Icons
/home/myAccount/opt/lib/python2.6/tmp
/home/myAccount/opt/lib/python2.6/lib-old
/home/myAccount/opt/lib/python2.6/lib-tk
/home/myAccount/opt/lib/python2.6/hotshot
/home/myAccount/opt/lib/python2.6/plat-linux2
/home/myAccount/opt/lib/python2.6/ctypes
/home/myAccount/opt/lib/python2.6/ctypes/test
/home/myAccount/opt/lib/python2.6/ctypes/macholib
/home/myAccount/opt/share
/home/myAccount/opt/share/man
/home/myAccount/opt/share/man/man1
And finally the contents of the sqlite3 directory:
-jailshell-3.2$ find `pwd`
/home/myAccount/opt/lib/python2.6/sqlite3
/home/myAccount/opt/lib/python2.6/sqlite3/__init__.pyo
/home/myAccount/opt/lib/python2.6/sqlite3/dump.pyc
/home/myAccount/opt/lib/python2.6/sqlite3/__init__.pyc
/home/myAccount/opt/lib/python2.6/sqlite3/dbapi2.pyo
/home/myAccount/opt/lib/python2.6/sqlite3/dbapi2.pyc
/home/myAccount/opt/lib/python2.6/sqlite3/dbapi2.py
/home/myAccount/opt/lib/python2.6/sqlite3/dump.pyo
/home/myAccount/opt/lib/python2.6/sqlite3/__init__.py
/home/myAccount/opt/lib/python2.6/sqlite3/dump.py
I feel like I need to add something into the sqlite3 directory - maybe sqlite3.so? But I don't know where to get that.
What am I doing wrong here? Please remember that I'm using a shared host so that means installing / compiling on another server and then copying the files over. Thanks! :)
Update
Just wanted to confirm that the answer from #samplebias did work out very well. I needed to have the dev package installed on the machine I was compiling from to get it to add in sqlite3.so and related files. Also found the link in the answer very helpful. Thanks #samplebias !
Python's build system uses a setup.py file to compile all of the native extensions, including sqlite3. It searches common operating system paths for the sqlite3 include and library dirs. If the sqlite3 development package is not installed Python will skip compiling the _sqlite3.so extension, but the pure Python portion of the sqlite3 package will still be installed.
You would need to have the operating system's sqlite3 development package installed when you compile Python and at runtime: sqlite3-devel on Centos, both libsqlite3-0 and libsqlite3-dev on Ubuntu.
Here's an example of the _sqlite3.so extension linkage on my Ubuntu system:
% ldd /usr/lib/python2.6/lib-dynload/_sqlite3.so | grep sqlite3
libsqlite3.so.0 => /usr/lib/libsqlite3.so.0 (0x00007f29ef3be000)
% dpkg -S /usr/lib/libsqlite3.so.0
libsqlite3-0: /usr/lib/libsqlite3.so.0
In general, the first thing to do is to ask your host. I seems a bit odd that SQLite is not installed (or installed properly). So they'll likely fix it quite fast if you ask them.
For python 2.4, you need sqlite and bindings, pysqlite 2 or aspw
None of the files listed in the sqlite folder is the _sqlite3.pyd Python shared library. Are you sure you compiled it when compiling Python? What does the build log say? I think there's a configure flag that needs to be passed.
Alternatively, just install pysqlite

Check if Python Package is installed

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?

Categories