Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: NameError: free variable 're' referenced before assignment in enclosing scope

Tags:

python

I have a strange NameError in Python 3.3.1 (win7).

The code:

import re

# ...

# Parse exclude patterns.
excluded_regexps = set(re.compile(regexp) for regexp in options.exclude_pattern)

# This is line 561:
excluded_regexps |= set(re.compile(regexp, re.I) for regexp in options.exclude_pattern_ci)

The error:

Traceback (most recent call last):
  File "py3createtorrent.py", line 794, in <module>
    sys.exit(main(sys.argv))
  File "py3createtorrent.py", line 561, in main
    excluded_regexps |= set(re.compile(regexp, re.I) for regexp in options.exclude_pattern_ci)
  File "py3createtorrent.py", line 561, in <genexpr>
    excluded_regexps |= set(re.compile(regexp, re.I) for regexp in options.exclude_pattern_ci)
NameError: free variable 're' referenced before assignment in enclosing scope

Note that line 561, where the error occurs, is the second line in the code above. In other words: re is not a free variable. It is simply the regular expression module and it can be referenced perfectly fine in the first line.

It seems to me that the reference to re.I is causing the problem, but I don't see how.

like image 785
robert Avatar asked May 14 '13 14:05

robert


3 Answers

Most likely, you are assigning to re (presumably inadvertently) at some point below line 561, but in the same function. This reproduces your error:

import re

def main():
    term = re.compile("foo")
    re = 0

main()
like image 109
alexis Avatar answered Nov 18 '22 22:11

alexis


"free variable" in the traceback suggests that this is a local variable in an enclosing scope. something like this:

 baz = 5

 def foo():
     def bar():
         return baz + 1

     if False:
          baz = 4

     return bar()

so that the baz is referring to a local variable (the one who's value is 4), not the (presumably also existing) global. To fix it, force baz to a global:

 def foo():
     def bar():
         global baz
         return baz + 1

so that it won't try to resolve the name to the nonlocal version of baz. Better yet, find where you're using re in a way that looks like a local variable (generator expressions/list comprehensions are a good place to check) and name it something else.

like image 37
SingleNegationElimination Avatar answered Nov 18 '22 22:11

SingleNegationElimination


The other explanations are perfect, but let me add another variant which I just discovered. Due to Python 3 preferring iterators over 'physical' lists one has to be more careful:

def foo():
    re = 3
    faulty = filter(lambda x: x%re, range(30))
    del re
    return faulty
list(foo())

The filter expression only gets evaluated after the return statement in the last line, in particular after del re. Hence the last line explodes with the error:

NameError: free variable 're' referenced before assignment in enclosing scope
like image 1
Yasin Zähringer Avatar answered Nov 18 '22 23:11

Yasin Zähringer