1

This question is specific to PyDev. The package structure looks like this:

app
├── __init__.py
├── sub1
│   ├── __init__.py
│   └── mod1.py
└── sub2
    ├── __init__.py
    └── mod2.py

The mod1.py module:

from __future__ import print_function

def f():
    print('It works!')

The mod2.py module:

from __future__ import absolute_import
from ..sub1 import mod1

if __name__ == '__main__':
    mod1.f()

Everything works beautifully from the shell, the python -m app.sub2.mod2 command prints:

It works!

as expected, all is fine. (The from __future__ import absolute_import line seems to have no effect: I can comment it out and everything still works just fine.)

If I click on mod2 in the PyDev IDE and try to Run As > Python Run, I get

ValueError: Attempted relative import in non-package

which is not surprising as the -m switch is not turned on by default. If I edit the Run/Debug settings for mod2: Arguments > VM Arguments and add -m here; the -m is most likely passed to the python interpreter but now I get:

/usr/bin/python: Import by filename is not supported.

The from __future__ import absolute_import line seems to have no effect; it does not matter whether I comment it out or not; I am using Python 2.7.

I am out of ideas at this point.

  • In PyDev, how can I run a module inside a package that uses relative imports?

  • How should I change the settings once (globally) such that whenever I try to run a module inside a package, PyDev does the right thing? (That is, I don't have to individually specify the settings for each module that I wish to run.)


The developer in person confirmed that it is not possible in PyDev yet; I have opened a ticket for it.

Running a module inside a package, using relative imports


UPDATE: As of Dec 2, 2016, the issue is resolved, see the accepted answer.

Ali
  • 56,466
  • 29
  • 168
  • 265
  • Seems like a pydev bug. Having said that, perhaps you could try adding a `__main__.py` module to your top-level package, and write Python code that invokes your desired sub-module. – Patrick Maupin Aug 09 '15 at 17:51
  • @PatrickMaupin Could you expand on the *"write Python code that invokes your desired sub-module"* part, please? – Ali Aug 09 '15 at 17:53
  • If you have a library that can also be used as an application, the cleanest way to separate app usage from library usage is to have a [`__main__.py`](http://stackoverflow.com/questions/4042905/what-is-main-py) file inside your top-level app. You put a parser in there that can, for example, let you decide which submodule to execute. – Patrick Maupin Aug 09 '15 at 18:02
  • @PatrickMaupin Thanks. Unfortunately, I don't see how a `__main__.py` could resolve my problem in PyDev: There are many-many modules that I may want to execute inside a package. I am probably missing your point, sorry. :( – Ali Aug 09 '15 at 18:43
  • That's where the bit of coding comes in. From the command line, or pydev, instead of `python -m app.sub2.mod2` you would do `python -m app sub2.mod2` (with a space instead of the first dot). And then `__main__.py` could have `import sys; __import__('.'+sys.argv.pop(1))`, or something like that but with better error checking and reporting. – Patrick Maupin Aug 09 '15 at 18:53
  • @PatrickMaupin OK. And how do I make PyDev to run `python -m app sub2.mod2` when I click on the `mod2.py` file and ask PyDev to run it? If I could do that somehow, then I could (most likely) make PyDev to run it as `python -m app.sub2.mod2` and that definitely would work. – Ali Aug 09 '15 at 20:20
  • Sorry, didn't think deeply enough about that part, and you're right -- in the IDE if that would work, then you could make your original approach work. You could import differently based on whether the module is `__main__` but that is a bit of a hack. – Patrick Maupin Aug 09 '15 at 20:30

1 Answers1

3

Edit:

In PyDev 5.4.0, there's now an option to run using the -m flag (which will import the module through its regular name and not as it was __main__ so that relative imports will work there).

You can enable it at: Preferences > PyDev > Run (i.e.: this will enable it for all runs -- maybe in the future there'll be an option to make it per run, but for now it's set globally for all launches).


Original answer:

The problem is that you have relative imports in your main module and PyDev executes the file with python path/to/file_to_execute.py instead of python -m my.module.

A simple fix is doing a separate main module which in turn imports a main() function from that module and runs it (although again: it can't have relative imports in the module executed as __main__ (this happens because the module is called __main__ and thus cannot resolve a relative import because it wasn't actually imported with a name which can be used to resolve the relative import).

Another fix would be changing the launch configuration to add the '-m my.module' in the VM arguments (go to run > run configurations to do that -- but you have to do that for each main module you want to run, including unit-tests).

And the last fix would be changing PyDev itself (so, please create a ticket for that in the PyDev tracker: https://www.brainwy.com/tracker/PyDev/ -- or submit a pull request, which would make adding that feature much faster ;) )

Fabio Zadrozny
  • 24,814
  • 4
  • 66
  • 78
  • I have enabled the option in PyDev as you indicated, but when I "See resulting command-line" I still get `python -u /full/path/to/file.py` and still have the same issue as the OP. I have restarted Eclipse to see if I would need it to take effect - same thing. – Michael Ressler Dec 17 '16 at 03:08