[Tutor] Hit Counter in Python

Charlie Clark Charlie Clark <charlie@begeistert.org>
Mon, 30 Jul 2001 18:46:41 +0200


>form = cgi.FieldStorage()
>:if form.has_key("Stats")			# Hidden field
>:	InFile = open("count.dat", "r")	# Text file with total hits
>:	Hits = InFile.readline()
>:	x = int(Hits) + 1
>:	h = str(x)
>:OutFile = open("count.dat", "w")
>:OutFile.write(str(x))
>:OutFile.close()
>:
>:
>:print "<P><H2>Jon Cosby's web page - Total hits:</H2><br><br> "
>:for i in h:
>:	print "<img src='images/" + i + "silver.gif'>"
>:print "</BODY>"
Ha, finally something which I know a little about ;-)

First of all counters are unreliable and unchic. The best thing to do is to 
read your logfile. There is a wonderful Python package out there from someone 
at Akamai which has all you need for it but implementing something like a 
counter has it's uses if you need to provide verifiable statistics (eg. for 
an online magazine). You can do this with script but you don't need a form. 
The usual way is to embed a tiny image in each page (say 1 x 1) and set the <
img> tag to connect to the script, increment and supply the image to the 
browser. This can be configured to beat proxies and caches and you can choose 
to record additional information - of course anything that's in the header 
can also be automatically logged. This is how the ivw verifies online 
circulation in Germany.

Your html maybe something like:
<img src = "/cgi-bin/do_count.cgi" alt = "" width = "1" height = "1">

Your script only needs to do read, increment and write...

>InFile = open("count.dat", "r")	# Text file with total hits
>Hits = InFile.readline()
>x = int(Hits) + 1
>h = str(x)
mm, this isn't quite right in style. Someone posted a link to Guido's notes 
on style and convention for me the other week. "InFile" would look like a 
class to many a pythoneer. Sorry. I did read it but didn't bookmark it. But 
it was over on Sourceforge

#! /bin/env python             # or whatever you need to do this in windows
# simple counter script

try:
    file_in = open("count.txt", "r")
    count = int(file_in.readline())     # it *is* a text file
    file_in.close()                     
except:
    open("count.txt", "w").write("0")   # so we don't choke on the first
    open("count.txt", "r").close()      # request
    count = 0     

file_out = open("count.txt", "w")
count += 1
file_out.write(str(count))

Write another script to display the counter. I think you might like to modify 
that as well. You've got a set of images 1..0silver.gif ? And you want to 
display the number of hits on the counter with a combination of those. I'm 
sure there's a nice way of doing that. I know you can loop through an integer 
but still you should separate the loop from it's contents

Let's say you've had 773 pages called up.
count = '773'

def show_image(i):
    print '<img src = "/images/%dsilver.gif">' %(i)   # or your string 
addition

for i in count:
    show_image(int(i))    

Can anybody tell me of a nicer way of doing this?

Charlie