简体   繁体   中英

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

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. ie 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM