问题
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.
回答1:
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 ;) )
来源:https://stackoverflow.com/questions/31904307/how-to-run-a-module-inside-a-package-using-relative-imports