classification
Title: SystemError: Parent module '' not loaded, cannot perform relative import
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.6
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: brett.cannon Nosy List: Arfrever, Rosuav, auslander1970, brett.cannon, eric.snow, flox, fossilet, ncoghlan, pitrou, python-dev
Priority: normal Keywords: 3.3regression

Created on 2013-05-20 01:01 by flox, last changed 2016-01-23 00:41 by brett.cannon. This issue is now closed.

Messages (9)
msg189630 - (view) Author: Florent Xicluna (flox) * (Python committer) Date: 2013-05-20 01:01
When executing a submodule, there's a SystemError in 3.3 where we used to receive a ValueError.

mkdir marsu
touch marsu/__init__.py
echo "from .houba import bi" >> marsu/pilami.py

./python marsu/pilami.py

Traceback (most recent call last):
  File "marsu/pilami.py", line 2, in <module>
    from .houba import bi
SystemError: Parent module '' not loaded, cannot perform relative import


In Python 3.2 (or Python 2.7):

./python3.2 marsu/pilami.py

Traceback (most recent call last):
  File "marsu/pilami.py", line 2, in <module>
    from .houba import bi
ValueError: Attempted relative import in non-package
msg189636 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2013-05-20 03:29
For the specific case given, both error messages are misleading anyway - the problem is attempting to directly execute a module inside a package instead of using "-m".

However, for the case of attempting a relative import from a top level module, the old message is indeed preferable.
msg189872 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2013-05-23 18:00
The line raising the exception is http://hg.python.org/cpython/file/f7992397e98d/Lib/importlib/_bootstrap.py#l1518 .

If you're sure it's a regression feel free to change what exception is raised.
msg189899 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-05-24 06:37
User code should generally not see any SystemErrors (even when choosing wacky module names :-)), so IMHO this is a regression.
msg258230 - (view) Author: Chris Angelico (Rosuav) * Date: 2016-01-14 21:55
This still happens in current CPython, and doesn't even require a package:

rosuav@sikorsky:~$ echo 'from . import x' >syserr.py
rosuav@sikorsky:~$ python3 syserr.py
Traceback (most recent call last):
  File "syserr.py", line 1, in <module>
    from . import x
SystemError: Parent module '' not loaded, cannot perform relative import


This just caused some confusion for a student of mine who had migrated from Python 2. Converting intra-package imports from "import spam" to "from . import spam" made them work; converting a non-package import the same way caused this problem. ImportError would be massively preferable.

But I'm not understanding something here. If I set __package__ inside the module, the behaviour changes accordingly:

rosuav@sikorsky:~$ cat syserr.py 
__package__ = 'sys'
from . import version
print(version)
rosuav@sikorsky:~$ python3 syserr.py 
3.6.0a0 (default:ac94418299bd+, Jan 15 2016, 08:44:02) 
[GCC 4.9.2]


Leaving __package__ unset has it implicitly be None. Whether it's None or '', the package checks should simply not be made - see three lines above the line Brett linked to (in today's code, that's https://hg.python.org/cpython/file/ac94418299b/Lib/importlib/_bootstrap.py#l925 - hasn't changed). So I'm not sure why the checks are even happening. However, that probably means more about my exploration and testing than it does about the code; editing the text of the message doesn't result in a change, so I'm obviously not updating the frozen version.
msg258261 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2016-01-15 02:27
The problem is in Python/import.c: https://hg.python.org/cpython/file/default/Python/import.c#l1453 . While the Python code has a check that `package` is a truthy value, the accelerated C code doesn't. Adding a check that the string isn't empty or truthy should do the trick as there seems to already be a check for None earlier.

The other question is whether this should change back to ValueError for Python 2 compatibility or turn into ImportError as Chris and Eric Snow have independently suggested?

Either way I'm only going to change this in Python 3.6 since the current semantics have been this way since Python 3.3, so it's beyond the realm of regression and into fixing a design mistake.
msg258263 - (view) Author: Chris Angelico (Rosuav) * Date: 2016-01-15 02:53
If someone made a new way of importing and had it raise ValueError on some issue or other, I think there'd be complete consensus that that's the wrong exception. Yes, this is incompatible with Python 2 - but there are a lot of corner cases in the 3.3+ import code that differ from 2.7. What we have is a code error ("relative imports outside of packages don't make sense, dummy!") and the only difference is which exception is being raised (ValueError, SystemError, ImportError). It's not like working code has different semantics.

But even if ValueError is chosen, I would still greatly prefer that to SystemError. When my student told me he was getting SystemError, I started trying to diagnose a corrupted venv, not a buggy script.
msg258851 - (view) Author: Roundup Robot (python-dev) Date: 2016-01-23 00:39
New changeset c4e4886c6052 by Brett Cannon in branch 'default':
Issue #18018: Raise an ImportError if a relative import is attempted
https://hg.python.org/cpython/rev/c4e4886c6052
msg258852 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2016-01-23 00:41
Thanks to everyone for providing feedback. I went with ImportError in the end as that's what the pure Python implementation of __import__() already raised.
History
Date User Action Args
2016-12-06 12:59:07serhiy.storchakalinkissue28885 dependencies
2016-01-23 00:41:33brett.cannonsetstatus: open -> closed
resolution: fixed
messages: + msg258852

stage: test needed -> resolved
2016-01-23 00:39:12python-devsetnosy: + python-dev
messages: + msg258851
2016-01-15 02:53:25Rosuavsetmessages: + msg258263
2016-01-15 02:27:20brett.cannonsetstage: test needed
messages: + msg258261
versions: - Python 3.3, Python 3.4, Python 3.5
2016-01-15 01:56:49fossiletsetnosy: + fossilet
2016-01-14 22:12:57brett.cannonsetassignee: flox -> brett.cannon
2016-01-14 22:10:00brett.cannonlinkissue24752 superseder
2016-01-14 22:05:30auslander1970setnosy: + auslander1970
2016-01-14 21:55:11Rosuavsetnosy: + Rosuav

messages: + msg258230
versions: + Python 3.5, Python 3.6
2013-05-24 06:37:58pitrousetnosy: + pitrou
messages: + msg189899
2013-05-23 18:00:14brett.cannonsetassignee: flox
messages: + msg189872
2013-05-20 03:34:02Arfreversetnosy: + Arfrever
2013-05-20 03:29:02ncoghlansetmessages: + msg189636
2013-05-20 01:01:48floxcreate