importing a package that doesn't exist - python

I've never seen an import issue like this before. I removed a directory from site-packages and the corresponding package is still importable.
python2
> import google
> print(google.__path__)
['/home/bamboo/.local/lib/python2.7/site-packages/google']
However this directory doesn't actually exist
ls: cannot access /home/bamboo/.local/lib/python2.7/site-packages/google: No such file or directory
I've removed everything that I'm aware of that is related to it, but there must still be something hanging around.
Digging another level deeper I tried to reload google.
python2
> import google;
> reload(google);
ImportError: No module named google
So apparently it recognizes it is gone on reload.
Checking out sys.modules you get
python2
> import sys
> print(sys.modules)
{'google': <module 'google' (built-in)>, 'copy_reg': <module 'copy_reg' from '/usr/lib/python2.7/copy_reg.pyc'> ...
which indicates that apparently google is a built-in.
Note on motivation: Usually this sort of issue would be weird, but not a show stopper. The problem for me is that the google package is masking a different package of the same name.

tl,dr: use pip to uninstall Google packages completely.
There are two issues here:
strange import/reload behaviour of the google package
removal of the google package
import/reload behavior
I can reproduce the import/reload behaviour by installing the (Google) protobuf package (many Google packages will behave in the same way).
$ mktmpenv -p $(which python2)
...
$ python --version
Python 2.7.13
$ pip install protobuf
...
Installing collected packages: six, protobuf
Successfully installed protobuf-3.5.1 six-1.11.0
>>> import google
>>> print google.__path__
['~/virtual-envs/tmp-66cd9b4d01a8dec6/lib/python2.7/site-packages/google']
>>> import sys
>>> print sys.modules['google']
<module 'google' (built-in)>
>>> reload(google)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named google
I suspect what's going on here is that Google prefer to have all Google packages installed under a single google package, but this package is not designed to be importable, hence the unexpected reload behaviour. However importing subpackages by name works as expected:
>>> import protobuf
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named protobuf
>>> from google import protobuf
>>> protobuf.__path__
['~/virtual-envs/tmp-66cd9b4d01a8dec6/lib/python2.7/site-packages/google/protobuf']
>>> reload(protobuf)
<module 'google.protobuf' from '~/virtual-envs/tmp-66cd9b4d01a8dec6/lib/python2.7/site-packages/google/protobuf/__init__.pyc'>
>>>
Removal of the google package
The question states:
I removed a directory from site-packages and the corresponding package is still importable.
This can also be reproduced:
($ rm -rf ~/virtual-envs/tmp-66cd9b4d01a8dec6/lib/python2.7/site-packages/google
$ python
>>> import google
>>> print google.__path__
['~/virtual-envs/tmp-66cd9b4d01a8dec6/lib/python2.7/site-packages/google']
>>>
The problem here is that simply removing the google directory and its contents is not enough to completely uninstall whatever Google packages are present.
The site-packages directory still contains the file protobuf-3.5.1-py2.7-nspkg.pth, which contains this code (split into separate lines for readability, the original is a single line of semi-colon separated statements):
import sys, types, os
has_mfs = sys.version_info > (3, 5)
p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('google',))
importlib = has_mfs and __import__('importlib.util')
has_mfs and __import__('importlib.machinery')
m = has_mfs and sys.modules.setdefault('google', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('google', [os.path.dirname(p)])))
m = m or sys.modules.setdefault('google', types.ModuleType('google'))
mp = (m or []) and m.__dict__.setdefault('__path__',[])
(p not in mp) and mp.append(p)
The line
m = m or sys.modules.setdefault('google', types.ModuleType('google'))
is creating the google module in sys.modules if it doesn't already exist - this is why the google module is importable even after the directory has been deleted.
The correct way to remove the google module is by uninstalling google packages using pip:
pip uninstall protobuf
If pip isn't available in the build environment the it's a case of identifying any related files and folders (*dist-info/, *.pth) in site-packages and removing them manually.

Related

osx - Mac - Python 3.5 - ImportError: No module named 'cubicspline' when testing python package

I recently downloaded a package and when testing the package to see if everything works correctly I get the error ImportError: No module named 'cubicspline'. When following the trail to see where is error occurs I found that cubicspline.py (the file not being found) is in the same folder as extcurve_s16.py (the file calling cubicspline).
File "/Users/Austin/anaconda/lib/python3.5/site-packages/isochrones/schlafly/extcurve_s16.py", line 4, in <module>
import cubicspline
I've checked the permissions on the folder and I'm able to both read and write. There is also an __init__.py file in the folder. Any ideas here? I can't figure out why it wouldn't be able to call a file that is in the same folder. Here is the exact chunk of code for reference, as can be seen import numpy works fine.
import numpy
import cubicspline
The issue was resolved by cloning the isochrones package from Github instead of using pip install isochrones. There was some type of issue with the pip version.

No module named 'ASWBXML' [duplicate]

when I run mitmproxy command in command line, I get the following error.
% mitmproxy
Traceback (most recent call last):
File "/usr/local/bin/mitmproxy", line 7, in <module>
from libmproxy.main import mitmproxy
File "/usr/local/lib/python3.5/site-packages/libmproxy/main.py", line 5, in <module>
import thread
ImportError: No module named 'thread'
I googled this error and found this stackoverflow Q&A page.
pydev importerror: no module named thread, debugging no longer works after pydev upgrade
according to the page above, the error occurs because module "thread" is renamed to "_thread" in python3.
So, I know what's causing this error, but then what?
I don't know what to do now in order to get rid of this error.
I'm new to python. I've just installed Python and pip into my mac OSX as shown below because I want to use mitmproxy.
% which pip
/usr/local/bin/pip
% pip --version
pip 8.1.1 from /usr/local/lib/python3.5/site-packages (python 3.5)
% which python
/usr/bin/python
% which python3
/usr/local/bin/python3
% python --version
Python 2.7.10
% python3 --version
Python 3.5.1
could anyone please tell me what to do now?
Additional Info
As #linusg answered, I created "thread.py" file in "site-packages" directory and pasted the code below in "thread.py"
from _thread import *
__all__ = ("error", "LockType", "start_new_thread", "interrupt_main", "exit", "allocate_lock", "get_ident", "stack_size", "acquire", "release", "locked")
After I did this, "ImportError: No module named 'thread'" disappeared, but now I have another ImportError, which is "import Cookie ImportError: No module named 'Cookie'".
It seems that in Python 3, Cookie module is renamed to http.cookies (stackoverflow.com/questions/3522029/django-mod-python-error).
Now what am I supposed to do?
What I have in "site-packages" directory
% ls /usr/local/lib/python3.5/site-packages (git)-[master]
ConfigArgParse-0.10.0.dist-info/ mitmproxy-0.15.dist-info/
OpenSSL/ netlib/
PIL/ netlib-0.15.1.dist-info/
Pillow-3.0.0.dist-info/ passlib/
PyYAML-3.11.dist-info/ passlib-1.6.5.dist-info/
__pycache__/ pathtools/
_cffi_backend.cpython-35m-darwin.so* pathtools-0.1.2.dist-info/
_markerlib/ pip/
_watchdog_fsevents.cpython-35m-darwin.so* pip-8.1.1.dist-info/
argh/ pkg_resources/
argh-0.26.1.dist-info/ pyOpenSSL-0.15.1.dist-info/
backports/ pyasn1/
backports.ssl_match_hostname-3.5.0.1.dist-info/ pyasn1-0.1.9.dist-info/
blinker/ pycparser/
blinker-1.4.dist-info/ pycparser-2.14.dist-info/
certifi/ pyparsing-2.0.7.dist-info/
certifi-2016.2.28.dist-info/ pyparsing.py
cffi/ pyperclip/
cffi-1.6.0.dist-info/ pyperclip-1.5.27.dist-info/
click/ setuptools/
click-6.2.dist-info/ setuptools-19.4-py3.5.egg-info/
configargparse.py sitecustomize.py
construct/ six-1.10.0.dist-info/
construct-2.5.2.dist-info/ six.py
cryptography/ test/
cryptography-1.1.2.dist-info/ thread.py
easy_install.py tornado/
hpack/ tornado-4.3.dist-info/
hpack-2.0.1.dist-info/ urwid/
html2text/ urwid-1.3.1.dist-info/
html2text-2015.11.4.dist-info/ watchdog/
idna/ watchdog-0.8.3.dist-info/
idna-2.1.dist-info/ wheel/
libmproxy/ wheel-0.26.0-py3.5.egg-info/
lxml/ yaml/
lxml-3.4.4.dist-info/
In Python 3 instead of:
import thread
Do:
import _thread
You are trying to run Python 2 code on Python 3, which will not work.
As of April 2016, mitmproxy only supports Python 2.7. We're actively working to fix that in the next months, but for now you need to use Python 2 or the binaries provided at http://mitmproxy.org.
As of August 2016, the development version of mitmproxy now supports Python 3.5+. The next release (0.18) will be the first one including support for Python 3.5+.
As of January 2017, mitmproxy only supports Python 3.5+.
Go to you site-packages folder, create a file called thread.py and paste this code in it:
from _thread import *
__all__ = ("error", "LockType", "start_new_thread", "interrupt_main", "exit", "allocate_lock", "get_ident", "stack_size", "acquire", "release", "locked")
This creates an 'alias' for the module _thread called thread. While the _thread module is very small, you can use dir() for bigger modules:
# Examle for the Cookies module which was renamed to http.cookies:
# Cookies.py in site-packages
import http.cookies
__all__ = tuple(dir(http.cookies))
Hope this helps!
Easiest solution is to create a virtualenv with python2 and run mitmproxy on this virtualenv
virtualenv -p `which python2` .env
source .env/bin/activate
pip install mitmproxy
.env/bin/mitmproxy
The name of the file saved could be threading, this would give an error as threading is a predefined class in Python. Try changing the name of your file. It would help....

Import python package after installing it with setup.py, without restarting?

I have a package that I would like to automatically install and use from within my own Python script.
Right now I have this:
>>> # ... code for downloading and un-targzing
>>> from subprocess import call
>>> call(['python', 'setup.py', 'install'])
>>> from <package> import <name>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named <package>
Then I can continue like this:
>>> exit()
$ python
>>> from <package> import <name>
And it works just fine. For some reason, Python is able to pick up the package just fine if I restart after running the setup.py file, but not if I don't. How can I make it work without having the restart step in the middle?
(Also, is there a superior alternative to using subprocess.call() to run setup.py within a python script? Seems silly to spawn a whole new Python interpreter from within one, but I don't know how else to pass that install argument.)
Depending on your Python version, you want to look into imp or importlib.
e.g. for Python 3, you can do:
from importlib.machinery import SourceFileLoader
directory_name = # os.path to module
# where __init__.py is the module entry point
s = SourceFileloader(directory_name, __init__.py).load_module()
or, if you're feeling brave that your Python path knows about the directory:
map(__import__, 'new_package_name')
Hope this helps,
I downloaded from seaborn from GitHub.
Through command prompt, cd to downloads\seaborn folder
python install setup.py
Then using spyder from anaconda, checked if it was installed by running the following in a console
import pip
sorted(["%s==%s" % (i.key, i.version)
for i in pip.get_installed_distributions()])
Seeing that it was not there, go to tools and select "Update module names list"
Again trying the previous code in a python console, the lib was still not showing.
Restarting Spyder and trying import seaborn worked.
Hope this helps.

Installed package stealing namespace

I'm developing a package "jw.data" in Python 2.7.9, with a namespace of jw and a package data in in. I have put the canonical
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
in jw/__init__.py. When I run ./setup.py develop (in setup.py I have put namespace_packages=['jw']), then I have "jw" in jw.data.egg-info/namespace_packages.txt. Doing a
import jw.data
import jw.data.model
just works fine. So I guess I have set up the namespace package correctly.
Now I have written a package "jw.util", also in namespace jw, with a package util in it. As soon as I install it, importing jw.data or anything below it fails:
>>> import jw.data
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named data
After uninstalling jw.util it works again.
I used jw.util elsewhere, but not yet in a package within the jw namespace. It looks like jw.util is reserving the jw namespace.
I had the same problem with another namespace. There I noticed the package name in setup.py is just the same as the namespace plus package. I renamed all the packages from "namespace.packagex" to "namespace-packagex", and astonishingly enough it worked. I tried the same with jw.util and jw.data, but here that trick doesn't work. And I don't really believe the package name in setup.py has anything to do with the package hierarchy it contains, or has it?
Anyway, anybody got an idea what's going on here?
Seems to be a long-known bug in Python.
But there's a solution in https://github.com/pypa/setuptools/issues/250:
Put simply, append
;import pkg_resources; pkg_resources.fixup_namespace_packages('')
to the single line in module-nspkg.pth of the competing package in site-packages. The semicolon is required.

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