This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: if __debug__: has nonobvious behaviour when evaluating .pyo without -O
Type: behavior Stage:
Components: Versions: Python 3.1, Python 3.2, Python 2.7, Python 2.6
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: Timothy.Fitz, afriesen, brett.cannon, pitrou, r.david.murray, rhettinger
Priority: low Keywords:

Created on 2010-04-12 21:34 by afriesen, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
pythonbug.zip afriesen, 2010-04-12 21:34
unnamed brett.cannon, 2010-04-15 02:15
Messages (8)
msg102975 - (view) Author: Andy Friesen (afriesen) Date: 2010-04-12 21:34
In certain circumstances, "if __debug__" seems to be evaluating its "else" clause even when -O is not specified.  This can cause very  surprising behavior.

a.zip contains a single file named a/__init__.pyo.  It is the compiled form of the following code:

    if __debug__:
        print 'DEBUG'
    else:
        print 'RELEASE'
        if __debug__ == True:
            raise Exception("this is impossible")

pythonbug.py evaluates this script with the following:

    import sys
    sys.path = ['a.zip']
    import a

When using Windows Python 2.6.2 and 2.6.5, running pythonbug.py produces this output:

    RELEASE
    Traceback (most recent call last):
      File "pythonbug.py", line 3, in <module>
        import a
      File "__init__.py", line 8, in <module>
        raise Exception("this is impossible")
    Exception: this is impossible

When -O is passed, the exception is not raised.

My best guess is that the Python bytecode is optimizing the "if __debug__" test away in the produced .pyo, but does not actually affect the value of __debug__ or check more complex expressions involving __debug__.
msg102978 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2010-04-12 21:55
It's probably caused by optimizations in the peepholer indeed.
msg102979 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2010-04-12 22:00
Your assessment of what is going on, Andy, is correct; the peephole optimizer for bytecode optimizes away the `if __debug__` section of the `if` statement for .pyo files.

But that is actually a reasonable thing for the compiler to do as you are not supposed to run optimized bytecode with the interpreter not running under -O. Running a .pyo file under an interpreter run w/o -O is like compiling for 64-bit but then running on a 32-bit system; you are not following assumptions you told the compiler could be made about the runtime.

So I am closing this as 'wont fix'. Best solution is to simply not run bytecode directly and instead execute the source as bytecode should be treated more as an optimization than some directly executable file format. But if you must execute the bytecode directly, simply make sure you don't mix .pyo/.pyc with an improper setting of -O.
msg102990 - (view) Author: Timothy Fitz (Timothy.Fitz) Date: 2010-04-12 23:52
In this case bytecode isn't an optimization, it's a distribution choice (this bug reared it's ugly head in our closed-source downloadable client).

I think that implausible execution paths are still a bug. 

Running a .pyo without -O should be explicitly an error. For instance can we change python to reliably blow up at import time? Or implicitly run as if you added -O?
msg103072 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2010-04-13 18:51
So technically Python does not know that some bytecode was compiled with optimization flags on; that is simply not carried in the bytecode format. You also cannot rely on file name extensions as the bytecode could have been generated by an interpreter that used .pyo as the file extension for non-optimized bytecode. So you can't really make this an "explicit error" without changing the format of bytecode files.

As for a distribution choice for only shipping bytecode, you should then only ship .pyc files to avoid this issue.

Raymond who (most likely) added the optimization is already on the nosy list so he can decide to disagree with me if he wants, but I am personally still not viewing this as a bug.
msg103162 - (view) Author: Timothy Fitz (Timothy.Fitz) Date: 2010-04-15 01:03
Does that mean you agree that the behavior is a bug?

If we're agreed that the behavior is a bug, then it's just a matter of solving the implementation details. One suggestion is to compile in a __debug__ check at the top of every .pyo file, effectively prepending every file with "if __debug__ == True: raise AssertionError()". Another could be to add a header to the bytecode (clearly waiting for the next major release of Python).

We'll gladly contribute patches once a suitable implementation has been chosen.
msg103172 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-04-15 01:35
No, Brett said he thought it was not a bug.  If Raymond disagrees, he'll say so.  If I may attempt to channel Brett, I suspect his logic for closing it "won't fix" went more or less like this: "it might be theoretically possible to change this behavior, but it is not something we wish to do."

Unless Raymond disagrees, of course.
msg103176 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2010-04-15 02:15
On Wed, Apr 14, 2010 at 18:35, R. David Murray <report@bugs.python.org>wrote:

>
> R. David Murray <rdmurray@bitdance.com> added the comment:
>
> No, Brett said he thought it was not a bug.  If Raymond disagrees, he'll
> say so.  If I may attempt to channel Brett, I suspect his logic for closing
> it "won't fix" went more or less like this: "it might be theoretically
> possible to change this behavior, but it is not something we wish to do."
>

Yep, that's what I meant.
History
Date User Action Args
2022-04-11 14:56:59adminsetgithub: 52626
2010-04-15 02:15:13brett.cannonsetfiles: + unnamed

messages: + msg103176
2010-04-15 01:35:30r.david.murraysetnosy: + r.david.murray
messages: + msg103172
2010-04-15 01:03:23Timothy.Fitzsetmessages: + msg103162
2010-04-13 18:51:21brett.cannonsetmessages: + msg103072
2010-04-12 23:52:44Timothy.Fitzsetnosy: + Timothy.Fitz
messages: + msg102990
2010-04-12 22:00:04brett.cannonsetstatus: open -> closed

nosy: + brett.cannon
messages: + msg102979

resolution: wont fix
2010-04-12 21:55:17pitrousetpriority: low
versions: + Python 3.1, Python 2.7, Python 3.2
nosy: + rhettinger, pitrou

messages: + msg102978
2010-04-12 21:34:05afriesencreate