Diez B. Roggisch
1/3/2008 3:05:00 PM
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@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