3

For some reason, emacs does not seem capable of evaluating absolute imports for any python project I run. Here is my project layout:

├── loxy
│   ├── errors.py
│   ├── __init__.py
│   ├── loxy.py
│   ├── scanner.py
│   ├── token_.py
│   └── token_type.py
└── setup.py

When I enter an inferior python shell, I am incapable of importing any of my project's modules that are declared using absolute or relative imports. E.g.

from X.Y import y
from .Y import y

Marking the above and running python-shell-send-region, or just sending the whole buffer, results in a ModuleNotFoundError for any import that does either of the above.

The only format that is unaffected is:

from Y import y

But this is incompatible with packaging with pip, which I will often do to test the package as a whole as a program via local installs, pip install -e . from the root of the package. Pip will work just fine with either relative or absolute imports, but emacs' inferior repl works with neither currently. This puts me at an impasse.

Any ideas?

Extra details:

Auto completion works just fine with my setup. Virtualenvs are detected fine with pyenv-mode and imports work with any of the styles I listed above. This is probably a path related error, but I am not sure how/why it is happening.


Update

Answered my own question after wasting a lot of hours trying to fix my workflow. Not proud of it but hope it might help someone else better understand how python works from within emacs.

1
  • 2
    First thing to look at is sys.path. See what's there, and this may give you a hint about why things you are looking for not there. As an aside: did you install your project into your virtual environment, or did you, perhaps, modify PYTHONPATH to point at your project? Why do you think Python should know where your project is?
    – wvxvw
    Commented Aug 6, 2018 at 4:42

2 Answers 2

3

So it appears that emacs' built in python mode, at least as of 24.3, is now python.el rather than python-mode.el. This new version of python-mode for emacs does not, by default, remove the current directory from python's sys.path (PYTHONPATH) when ran, meaning the path for python includes '', the current working directory.

This is not a problem unless you run run-python while inside a module, say scanner.py, and try to import modules as if you are running the package as a script from its root. For example, the level of my project where setup.py and the subdirectory loxy.py exist. Why? With my situation, this means I have /home/username/code/loxy/loxy and /home/username/code/loxy on my sys.path. The former takes precedent and when I try to do an absolute import, python thinks that I'm treating my module loxy.py as a package proper, and thus fails to import.

My solution was simply running run-python from the dired root directory of my project rather than from within a module, thus setting my path correctly.

An alternative way to go about fixing this would be seeing what your sys.path is:

>>> import sys
>>> import pprint
>>> pprint.pprint(sys.path)

You will get a list of strings that represent what is currently in your sys.path.

The next step is correcting it. In my case, I didn't want my current working directory, '', so merely popping it off the list fixed it:

>>> sys.path.pop()
0

After a few hours of trying to solve the same problem, I am happy to find this:

My solution was simply running run-python from the root directory of my project rather than from within a module, thus setting my path correctly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.