Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compilation vs. Interpretation, Python has unexpected behaviour

I get an unexpected behavior of python execution.

if True:
    print("Hello")
else:
    I am an error. what can you do about it?

Now, this code doesn't raise a SyntaxError because the control never goes into the else statement. In compiled languages like C++ it gets an error. Even in Java, unused code is an error. But not in Python.

Now in this case:

x = 10
def foo():
    print(x)
    x += 1

The print statement raises an UnboundLocalError as specified here. According to the previous logic, this error should not be until the control encounters x+=1. But it does, like in any other compiled language.

Then how to determine when will the code run as compiled or interpreted?

Edit: If it is compiled into a bytecode .pyc file and then interpreted. Then why is the first example's else statement not detected?

like image 529
Abhishek Bera Avatar asked Dec 04 '25 11:12

Abhishek Bera


2 Answers

Opposite. Python compiles source into byte code before execution. The first case will raise a syntax error during compilation phase.

In the second case, the compiler sees that x is modified in the function so it binds x to the function object. The function namespace is created each time the function is called but the variable only appears when it has been assigned. Its only when you execute print(x) that python realizes you are asking for a local variable that hasn't been assigned. This is a common bug when not all execution paths set a variable like they should.

Slightly modifying the example, sometimes the local variable is set, other times it is not. When set, you see the variable in locals and the print works. When not set, the variable is not in locals and the print fails.

x = 10
def foo(val):
    if val:
        x = 1
    print(val, 'before', locals())
    print(x)
    print(val, 'after')
    x += 1

foo(True)
foo(False)

Output

True before {'val': True, 'x': 1}
1
True after
False before {'val': False}
Traceback (most recent call last):
  File "o.py", line 11, in <module>
    foo(False)
  File "o.py", line 6, in foo
    print(x)
UnboundLocalError: local variable 'x' referenced before assignment
like image 118
tdelaney Avatar answered Dec 07 '25 01:12

tdelaney


It always runs as interpreted; but the syntax checker is invoked on the entire file as the first step, which generates the bytecode file.

In both python 2.7 and 3.5 the code you've put at the top will result in a syntax error:

python3 junk.py
  File "junk.py", line 4
    I am an error. what can you do about it?
              ^
SyntaxError: invalid syntax

It shouldn't be possible to get a 'runtime' syntax error in python; the only way to achieve that is to dynamically import a module with a syntax error.

I'm not sure I've understood your question, but the error in the second case is a runtime error; it's like doing int x = 0; y = 10/x; in C; variable scope ('does x exist at this point?') is not resolved during the syntax parse in python.

--

Edit; here's a dump from my terminal:

Clank:tmp doug$ cat junk.py
if True:
    print("Hello")
else:
    I am an error. what can you do about it?

Clank:tmp doug$ python junk.py
  File "junk.py", line 4
    I am an error. what can you do about it?
       ^
SyntaxError: invalid syntax

Clank:tmp doug$ python3 junk.py
  File "junk.py", line 4
    I am an error. what can you do about it?
       ^
SyntaxError: invalid syntax
like image 35
Doug Avatar answered Dec 06 '25 23:12

Doug