2
votes

I am making a package in python3, using PyDev. One of my .py files has a simple relative import, from . import filename. When I use another file outside of the package to import from the package and test out that file it works fine, but running that file directly in PyDev fails with this error:

ImportError: attempted relative import with no known parent package

After a lot of searching, I found some code that works when I add it before any imports are made:

__path__ = [""] # indicates local directory
__package__ = ["package_name"]

Then everything runs fine. However, just a test, in that file I put this line: print(__name__)

The output is two strings!

package_name
__main__

I suspect this is just because it's in a package and being run directly, but then how do I do something like if __name__ == "__main__": ?

Here are some more outputs when I messed around with the __name__ var more:

print(repr(__name__))
# output
'package_name'
'__main__'

print(__name__.endswith("__main__"))
# output
False
True

print(type(__name__))
# output
<class 'str'>
<class 'str'>

I don't even understand how a variable could have two separate strings assigned to it. What is going on?

1
That sounds like this file is actually getting run twice. There are a few ways you might confuse the import system enough for that to happen. - user2357112 supports Monica
By far the easiest solution is to just not try to run package contents directly and not try to make the same file an importable module and a script, though. - user2357112 supports Monica
@user2357112 It being run twice makes sense, any ideas on how that could happen? And in response to your other comment, I think that's what I'll do for now. It's not really necessary for the file to be a runnable script, I was just interested in it not generating an error if it was run. Thanks for the help! - makeworld
The most likely scenario is that this code is outside any if __name__ == '__main__' guard, and that this file is also getting imported as a module in the course of running it as a script. In that case, the file will be executed twice, once as __main__ and once as whatever module. if __name__ == '__main__' is supposed to guard against most of the negative effects of that, but it doesn't entirely work - for example, even with an if __name__ == '__main__' guard, classes defined in such a file will be defined twice. - user2357112 supports Monica
[PEP 8][1] discourages using of relative imports. - betontalpfa

1 Answers

0
votes

This is a known Python issue... files run as __main__ cannot have relative imports in them unless they're run with the -m flag (which imports the module with the name given and then changes its __name__ to run it as __main__.

By default PyDev just runs the file regularly, but you can also ask it to run the file by its computed module name (see preferences > PyDev > Run > Launch modules with "python -m mod.name").

Personally, I suggest you don't put relative imports in your __main__ module (because then users won't also be able to run your module as python filename.py and will also have to run with the -m flag), but if that's Ok for you, you can enable that option in PyDev.