7

I've recently ported my Python project to run on Python 3.1. For that I had to adopt the policy of relative imports within the submodules and subpackages of my project. I've don’t that and now the project itself works, but I noticed I can't execute any of the subpackages or submodules in it. If I try, I get "builtins.ValueError: Attempted relative import in non-package". I can only import the whole project.

Is this normal?

Ram Rachum
  • 84,019
  • 84
  • 236
  • 374

3 Answers3

4

Yes, it's normal. If you want to execute a module that is also a part of a package (in itself a strange thing to do) you need to have absolute imports. When you execute the module it is not, from the interpreters point of view, a part of a package, but the __main__ module. So it wouldn't know where the relative packages are.

The standard way to do it is to have functions in the packages, and separate executable scripts that call the functions, as this enables you to put the executable scripts outside the module, for example in /usr/bin

Lennart Regebro
  • 167,292
  • 41
  • 224
  • 251
  • 1
    Wow, I find this philosophy weird. For example, I have in my project a package `life`. Its absolute path is `garlicsim.bundled.simulation_packages.life`. I would have liked to be able to run it by itself, since it doesn't depend on anything in `garlicsim`. Why shouldn't I be able to run it by itself? – Ram Rachum Oct 18 '09 at 19:55
  • 1. If it doesn't depend on anything in garlicsim, then why is it in garlicsim? 2. Why would you not be able to run it by itself? You can run it by itself, but you need to have absolute imports, that is `from garlicsim.bundled.simulation_packages.life import whatever`. 3. What is the philosophy that you find weird? I didn't mention any philosopfy, so I don't know what "this" philosophy is. – Lennart Regebro Oct 18 '09 at 20:16
  • 3
    1. It's just bundled in. But I could take another example, of `garlicsim.asynchronous_crunching.crunchers`, which is a subpackage that garlicsim is dependent on, but it's not dependent on garlicsim. (2) Say if I want to move it to another package someday, why shouldn't I be able to, without the fuss of editing import lines? (3) Maybe I should have said "policy" instead of "philosophy". This attitude, of being able to either (a) execute the package independently, or (b) port it to other packages easily, _but not both_. – Ram Rachum Oct 18 '09 at 20:40
  • Geez. What is it with people arguing against the answers today? :-) Can't you move it easily? Isn't a search and replace easy? You need to do that search and replace in garlicsim anyway. --- There is no such policy. It is however not possible to do what you want, but then again, there is no compelling reason to do it. --- If you don't agree with the change in how relative imports have changed in Python 3 (and there are *very* good reasons for it changing) than complain on Python-dev, and prepare to get flamed, :-) – Lennart Regebro Oct 18 '09 at 21:04
3

You can use -m flag of the python interpreter to run modules in sub-packages (or even packages in 3.1.).

Benjamin Peterson
  • 19,297
  • 6
  • 32
  • 39
  • I'd say you *have* to use the `-m` switch; it's not that you *can*. I like calling python files directly, because I don't need to remember the switch and my shell nicely auto completes. – Frederick Nord Jun 24 '16 at 14:37
  • See this answer to if you're interesting in running an executable python script from a submodule: http://stackoverflow.com/a/11537218/730150 – krumpelstiltskin Nov 29 '16 at 13:59
-1

I had the same problem and I considered the -m switch too hard.

Instead I use this:

try:
    from . import bar
except ValueError:
    import bar

if __name__ == "__main__":
    pass
Community
  • 1
  • 1
sorin
  • 161,544
  • 178
  • 535
  • 806
  • Implicit relative imports are deprecated and removed in python 2.7. – habnabit Sep 13 '10 at 16:05
  • Arron, you are right but I do not see how this change my solution. This works with any python 2.5-3.1. – sorin Sep 13 '10 at 18:27
  • no, this does not work in 3.x. It's removed in 2.7+, which includes 3.0-3.1. – habnabit Sep 14 '10 at 08:19
  • @Arron, have you tried the above code and it fails run? I guess not, I did run it on Python 2.6, 2.7 and 3.1. The change you are talking about affects only the behavior of lines like `import bar` and this is why I came up with this usage, to convince Python to prefer the loading of `bar` module from current directory if possible. – sorin Sep 14 '10 at 08:27
  • @AaronGallagher, what do you mean? Of course I can import a file in the working directory named `bar.py` from the main script or the interactive shell. I just can't do it from a module. – Turion Feb 11 '12 at 19:57
  • For python3 compatibilty, `except (ValueError, SystemError)` seems to work. – Frederick Nord Jun 24 '16 at 14:36