pip installing a package with the same namespace as a local package - python

I am using Python 3.6.5, installed via miniconda. My issue is arising from the fact that I'm pip installing a package that has the same namespace as a local package. After pip installing this package, I can no longer import from the local package. I receive a ModuleNotFoundError error. The namespaces need to stay this way, if possible.
Here is my directory structure:
/root
stuff
- __init__.py
- my_stuff.py
app.py
init.py
__import__('pkg_resources').declare_namespace(__name__)
app.py
from stuff.my_stuff import my_fun
This works fine until I pip install the package with the same namespace, "stuff". After pip installing the package, the import statement, from stuff.my_stuff import my_fun throws the following error: ModuleNotFoundError: No module named 'stuff.my_stuff'. I kind of understand why. When importing modules in Python, it will look for built-in modules first, then sys.path, PYTHONPATH etc...
Here's the part thats really confusing me. If I create another arbitrary local module, like some_stuff, as shown below:
/root
stuff
- __init__.py
- my_stuff.py
some_stuff
- __init__.py
- more_stuff.py
app.py
and if I then run:
app.py
from some_stuff.more_stuff import more_fun
from stuff.my_stuff import my_fun
Everything works as expected. i.e. if I import some_stuff.more_stuff before stuff.my_stuff, everything works. But not vice versa. Solely importing stuff.my_stuff causes the ModuleNotFoundError.
app.py
# The code above works, but this causes the error
from stuff.my_stuff import my_fun
What is causing this behaviour? How can I solve this issue of locally referencing a package with the same namespace as one that was pip installed?
Edit:
I continued experimenting and noticed that when I remove all __init__.py files, everything works as expected. I came across this post: Since Python 3.3, a folder without an __init__.py can be considered part of an implicit namespace package. I'm still confused about the behaviour mentioned above though.

This SO question should answer your question
I am still putting the original answer here for convenience.
It's not possible to change "import path" (installed name) by specifying arguments to pip. You can, however, make some changes to the package after installing:
use pip install -e git+http://some_url#egg=some-name that way even if both packages have the same import path, they will be saved under different directories (using some-name provided after #egg=). After this you can go to the source directories of packages (usually venv/src/some-name) and rename some folders to change import paths
fork the repository, make changes, then install the package from that repository. Or you can publish your package on PyPI using different name and install it by that name
use pip download to put one of the packages in your project, then rename folders as you like

Related

cannot import from partially initialized module 'noise'

I have the current 'noise' package 2.2 in python3.8
It appears to have a circular import problem;
I do not believe I have any similarly named files in my own folders.
My code:
import noise
Result>
import noise
File "C:\Python\Python38\lib\site-packages\noise\__init__.py", line 12, in
from . import _perlin, _simplex
ImportError: cannot import name '_perlin' from partially initialized module 'noise' (most likely due to a circular import) (C:\Python\Python38\lib\site-packages\noise\__init__.py)
From a Github issue regarding this problem:
What's happening is that Python prefers to look for modules in relative paths before absolute paths. Since you can import noise from the repo directory, that means it's probably already in your python path(an absolute path).
Say this repository lives in foo/noise/ and now you are in foo/ if you go up a directory and try to run import noise. Python will see that the local directory noise/ as a module because it has an init.py file and try to import the directory instead of the module installed in your python path. Since this module requires the _noise and _simplex C extensions to be compiled, this wont work.
I'd recommend removing or renaming this repo directory from your project and use pip to install noise if you haven't already. (pip install noise)
If you really want to install from source and not install into your system, then, in the noise/ repository, run python setup.py build to build locally and grab dist/lib*/noise/ and put that directory into your project directory.
Alternatively use python setup.py install in the noise/ repository to install from source into your Python path.

Need help understanding this issue regarding relative vs absolute imports in Python

I was getting an error when I wanted to install a certain Python package in a specific folder (using pip install -t), and then import a module from that package.
I posted the issue on the package's Github and it turns out I can't install a package in a certain folder; that it isn't supported for the package to be installed that way.
Even without google collab, I can reproduce the import error when trying to install sklearn in some specific folder with pip install -t sklearnFolder then importing it as sklearnFolder.sklearn.manifold.
That is not a supported way of installing / using scikit-lean. One reason why it wouldn't work is that a few modules in scikit-learn use absolute imports (e.g. from sklearn import something) which will fail with such setup.
You should either install it with pip install or if you want to have it in some specific folder, clone the repo to that folder, then run pip install -e , in both cases it will be imported as sklearn.
From https://github.com/scikit-learn/scikit-learn/issues/11656
I don't quite get the explanation.
I thought something like
from folderName.package import module
is the same as
from package import module
Because they're both absolute imports. As in, they both completely specify the path of the imported module. So there is something off about my understanding but I don't know what it is.
In an import you do not specify the folderName to prefix a package. If the package is installed or in the python path, then you just use the package name to import.
# Assume the below structure is under a directory (folder) called /app/home/packages.
reservation/ This is your top-level pacakge
__init__.py Initialize the package
hotels/ Subpackage for hotel reservations
__init__.py
slots.py
bid.py
demand.py
...
restaurents/ Another Subpackage under hotels
__init__.py
cuisine.py
hours.py
tableslots.py
...
rewards/ Subpackage for rewards
__init__.py
points.py
discounts.py
membersonly.py
...
As the package is under /app/home/packages, then the following import is NOT valid as you prefix the folder name.
from packages.reservation import hotels
The correct way to import is from the actual package which has the package initialization __init__.py. If you see in the example, reservation folder has __init__.py.
from reservation import hotels
If you want to import the sub module under the hotels, then you will prefix with the package:
from reservation.hotels import restaurents
Alternatively you can import directly the sub module but you will have to prefix with the package when you use it:
import reservation.hotels.restaurents

Python3 circular library import (module not defined)

I am building a python library, yet can't seem to solve this rather trivial import error. My folder structure is as follows:
./examples/somecode.py
./library/code/specific/__init__.py and other files for this submodule
my somecode.py looks something in the lines of
from library.code import specific
... do things with specific ...
I get specific not defined error.
but only if I am in the examples folder. Interestingly enought, the code works if I start the interpreter from the ./ folder.
What am I doing wrong?
EDIT:
the library is installed with python3 setup.py install

My package installed with pip install shows no modules

I have a simple Python project with effectively one package (called forcelib) containing one module (also called forcelib):
- setup.py
- forcelib
|- __init__.py
|- forcelib.py
My setup.py is copied from the official example and has the obvious edits.
The problem is that I can install the forcelib package using pip but when I import forcelib, it only has the "double-underscore" attributes visible. That is, I cannot see the forcelib module.
Example to replicate:
git clone https://github.com/blokeley/forcelib
cd forcelib
pip install -e .
python
import forcelib
print(forcelib.__version__) # Correctly prints 0.1.2
dir(forcelib) # The only contents are the __version__, __path__ etc. double-underscore attributes. I had expected to see forcelib, example_read etc.
Perhaps I'm supposed to distribute just the module rather than bother with a package.
The (very small) project is on GitHub.
Any advice would be much appreciated.
It seems that there are 2 ways of doing it:
Keep the same directory structure but put the following in __init__.py
from .forcelib import *
Distribute a module, not a package. Follow the instructions to use the py_modules argument rather than the packages argument in setup.py. This would mean restructuring the project to:
setup.py
forcelib.py
Approach (1) can be seen here. It has the advantage of hiding the private functions and attributes (anything not in __all__), but the client can still see the module forcelib.forcelib, which I don't think it should.
Approach (2) can be seen here. It is simpler, but has the disadvantage that it does not hide private functions and attributes.
Download zip file and extract zip after go to forcelib-master directory
then open command prompt and go to forcelib-master directory in command prompt and run command
python setup.py install
It will install packages successfully

Unable to import from __init__.py [duplicate]

I'm having a hard time understanding how module importing works in Python (I've never done it in any other language before either).
Let's say I have:
myapp/__init__.py
myapp/myapp/myapp.py
myapp/myapp/SomeObject.py
myapp/tests/TestCase.py
Now I'm trying to get something like this:
myapp.py
===================
from myapp import SomeObject
# stuff ...
TestCase.py
===================
from myapp import SomeObject
# some tests on SomeObject
However, I'm definitely doing something wrong as Python can't see that myapp is a module:
ImportError: No module named myapp
In your particular case it looks like you're trying to import SomeObject from the myapp.py and TestCase.py scripts. From myapp.py, do
import SomeObject
since it is in the same folder. For TestCase.py, do
from ..myapp import SomeObject
However, this will work only if you are importing TestCase from the package. If you want to directly run python TestCase.py, you would have to mess with your path. This can be done within Python:
import sys
sys.path.append("..")
from myapp import SomeObject
though that is generally not recommended.
In general, if you want other people to use your Python package, you should use distutils to create a setup script. That way, anyone can install your package easily using a command like python setup.py install and it will be available everywhere on their machine. If you're serious about the package, you could even add it to the Python Package Index, PyPI.
The function import looks for files into your PYTHONPATH env. variable and your local directory. So you can either put all your files in the same directory, or export the path typing into a terminal::
export PYTHONPATH="$PYTHONPATH:/path_to_myapp/myapp/myapp/"
exporting path is a good way. Another way is to add a .pth to your site-packages location.
On my mac my python keeps site-packages in /Library/Python shown below
/Library/Python/2.7/site-packages
I created a file called awesome.pth at /Library/Python/2.7/site-packages/awesome.pth and in the file put the following path that references my awesome modules
/opt/awesome/custom_python_modules
You can try
from myapp.myapp import SomeObject
because your project name is the same as the myapp.py which makes it search the project document first
You need to have
__init__.py
in all the folders that have code you need to interact with.
You also need to specify the top folder name of your project in every import even if the file you tried to import is at the same level.
In your first myapp directory ,u can add a setup.py file and add two python code in setup.py
from setuptools import setup
setup(name='myapp')
in your first myapp directory in commandline , use pip install -e . to install the package
pip install on Windows 10 defaults to installing in 'Program Files/PythonXX/Lib/site-packages' which is a directory that requires administrative privileges. So I fixed my issue by running pip install as Administrator (you have to open command prompt as administrator even if you are logged in with an admin account). Also, it is safer to call pip from python.
e.g.
python -m pip install <package-name>
instead of
pip install <package-name>
In my case it was Windows vs Python surprise, despite Windows filenames are not case sensitive, Python import is. So if you have Stuff.py file you need to import this name as-is.
let's say i write a module
import os
my_home_dir=os.environ['HOME'] // in windows 'HOMEPATH'
file_abs_path=os.path.join(my_home_dir,"my_module.py")
with open(file_abs_path,"w") as f:
f.write("print('I am loaded successfully')")
import importlib
importlib.util.find_spec('my_module') ==> cannot find
we have to tell python where to look for the module. we have to add our path to the sys.path
import sys
sys.path.append(file_abs_path)
now importlib.util.find_spec('my_module') returns:
ModuleSpec(name='my_module', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fa40143e8e0>, origin='/Users/name/my_module.py')
we created our module, we informed python its path, now we should be able to import it
import my_module
//I am loaded successfully
This worked for me:
from .myapp import SomeObject
The . signifies that it will search any local modules from the parent module.
Short Answer:
python -m ParentPackage.Submodule
Executing the required file via module flag worked for me. Lets say we got a typical directory structure as below:
my_project:
| Core
->myScript.py
| Utils
->helpers.py
configs.py
Now if you want to run a file inside a directory, that has imports from other modules, all you need to do is like below:
python -m Core.myscript
PS: You gotta use dot notation to refer the submodules(Files/scripts you want to execute). Also I used python3.9+. So I didnt require neither any init.py nor any sys path append statements.
Hope that helps! Happy Coding!
If you use Anaconda you can do:
conda develop /Path/To/Your/Modules
from the Shell and it will write your path into a conda.pth file into the standard directory for 3rd party modules (site-packages in my case).
If you are using the IPython Console, make sure your IDE (e.g., spyder) is pointing to the right working directory (i.e., your project folder)
Besides the suggested solutions like the accepted answer, I had the same problem in Pycharm, and I didn't want to modify imports like the relative addressing suggested above.
I finally found out that if I mark my src/ (root directory of my python codes) as the source in Interpreter settings, the issue will be resolved.

Categories

Resources