problem with global var

Diez B. Roggisch deets at nospam.web.de
Thu Jan 3 10:05:07 EST 2008


Bruno Ferreira wrote:

> Hi,
> 
> I wrote a very simple python program to generate a sorted list of
> lines from a squid access log file.
> 
> Here is a simplified version:
> 
> ##################################
> 1  logfile = open ("squid_access.log", "r")
> 2  topsquid = [["0", "0", "0", "0", "0", "0", "0"]]
> 3
> 4  def add_sorted (list):
> 5     for i in range(50):
> 6          if int(list[4]) > int(topsquid[i][4]):
> 7              topsquid.insert(i,list)
> 8              break
> 8      # Max len = 50
> 10     if len(topsquid) > 50:
> 11         topsquid = topsquid[0:50]
> 12
> 13 while True:
> 14     logline = logfile.readline()
> 15     linefields = logline.split()
> 16
> 17     if logline != "":
> 18         add_sorted (linefields)
> 19     else:
> 20         break
> 21
> 22 for i in range (len(topsquid)):
> 23     print topsquid[i][4]
> ####################################
> 
> When I execute the program _without_ the lines 10 and 11:
> 
> 10     if len(topsquid) > 50:
> 11         topsquid = topsquid[0:50]
> 
> it runs perfectly.
> 
> But if I execute the program _with_ those lines, this exception is thrown:
> 
> bruno at ts:~$ python topsquid.py
> Traceback (most recent call last):
>   File "topsquid.py", line 20, in <module>
>     add_sorted (linefields)
>   File "topsquid.py", line 6, in add_sorted
>     if int(list[4]) > int(topsquid[i][4]):
> UnboundLocalError: local variable 'topsquid' referenced before assignment
> 
> 
> Note that now the error shown is not related with the lines 10 and 11,
> but wiht a line prior to them.
> 
> Any hints?

Use 

def add_sorted(list):
   global topsquid
   ...

to make topsquid a global variable to add_sorted. Otherwise python sees that
it gets referred by in the if-statement before assigning to it, thus
resulting in the error you see. 

The reason for this is that a (limited) static analysis of python-code is
performed to determine which variables are local to a function and which
not. The criteria essentially is the appearance on the left-hand-side of an
expression makes a variable (or name) local to that function. Which makes
it require the explicit global declaration.

Apart from that there are quite a few things worth mentioning in your code:

 - don't shadow built-in names like list

 - it's superfluous to do

for i in xrange(len(some_list)):
    .. some_list[i] ..

as you do, unless you need the index. Instead do

for element in some_list:
   ... element ...

If you need an index, do 

for i, element in enumerate(some_list):
   ...

 - don't use range, use xrange if you don't need a list but rather 
   want to enumerate indices.

 - the while-loop is superfluous as well, just do

for line in logfile:
  ...

or if your python is older do

for line in logfile.xreadlines():
  ...

Diez




More information about the Python-list mailing list