python: เกร็ด cgi

บันทึกเกร็ดเกี่ยวกับการใช้ไพธอนทำเว็บ ด้วย cgi

  • ต้องมีบรรทัด Content-type: text/html\r\n เป็นบรรทัดแรก apache ถึงจะตีความเป็น HTML
    #!/usr/bin/env python
    print "Content-type: text/html\r\n"
    ...
  • ควรบอกระบบว่าไฟล์เราเข้ารหัสแบบไหน เช่นถ้าเป็น utf-8
    #!/usr/bin/env python
    # -*- coding: utf8 -*-
    ...

    จาก Defining Python Source Code Encodings

  • ถ้าเราทำโปรแกรมของเราเป็นแพกเกจ หากยังไม่ได้ทำติดตั้งลงใน site-package แต่ยังเป็นเพียงไดเรกทอรี่อยู่ เวลาอิมพอร์ต ต้องใช้ทั้งสองคำสั่งคือ ทั้ง from ... import * และ import ... เช่นสมมุติแพกเกจเราชื่อ dweb ใช้
    ...
    import dweb
    from dweb import *
    ...
  • การใช้งานกับ apache2 แบบ CGI ธรรมดา พารามิเตอร์ที่ต้องใช้ในไฟล์ htaccess คือ
    $ vi .htaccess
    DirectoryIndex index.py
    Options +Indexes ExecCGI FollowSymLinks MultiViews
    AddHandler cgi-script .py
    AddType application/x-python-code .pyc .pyo
    AddHandler python-program .pyc .pyo
Topic: 

python: ข้อผิดพลาดของ cgi กับเนื้อหาเว็บ

การใช้โมดูล cgi ในการสร้างเว็บ ต้องระวังเรื่องเนื้อหาในเพจให้ดี
ให้ระวังคือ

  • อย่าให้มีแท็ก <head> หลุดเข้ามาในส่วนของ <body>
  • ระวังแท็ก <link rel="..." src="..." /> ต้องมีค่าให้เรียบร้อย ค่าใน src ห้ามมั่ว

ไม่งั้นฟังก์ชั่น cgi.FieldStorage จะทำงานผิดพลาดไปหมด ดีบักยากด้วย เพราะแสดงผลออกมาถูก แต่การทำงานภายในผิดหมด

Topic: 

python: วิธีใช้งาน Cookie

เอามาจาก ug's Python CGI scripts: cookie.py

การเซ็ต Cookie
สร้างไฟล์ชื่อ setcookie.py

#!/usr/bin/env python
import Cookie

c1 = Cookie.SimpleCookie()
# Create a cookie in c1
# This will be temporary and will disappear when the session is closed
c1["cracker"] = "hello"
# The RFC says you should always set this but it seems to work ok without it
c1["cracker"]["version"] = 1

# Create another one
c1["bisquit"] = "whatever"
# Make the browser store it for one hour
c1["bisquit"]["max-age"] = 3600 # Time to keep, in seconds
c1["bisquit"]["expires"] = 3600 # Obsolete, but Netscape still seems to require it
c1["bisquit"]["version"] = 1

# Print the headers that sets the cookies
print c1

# Show html page
print "Content-type: text/html\r\n"
print "<h1>Cookie is set</h1>"

สั่งรันจากบราวเซอร์หนึ่งครั้ง Cookie จะถูกเก็บเข้าในเครื่องของ Client

การรับ Cookie
สร้างไฟล์ชื่อ getcookie.py

#!/usr/bin/env python
import Cookie, os

# Show html page
print "Content-type: text/html\r\n"
print "<h1>Get cookie</h1>"

try:
    cookie = os.environ["HTTP_COOKIE"]
    print "HTTP_COOKIE="+cookie
    print "<p>"
    c2 = Cookie.SimpleCookie()
    c2.load(os.environ["HTTP_COOKIE"])
    print "<pre>"
    print c2
    print "</pre>"

    print 'c2["bisquit"].value =', c2["bisquit"].value, "<br />\n"
    print 'c2["cracker"].value =', c2["cracker"].value
except:
    print "No cookies were received"

สั่งรันจากบราวเซอร์ จะเห็นตัวแปร bisquit และ cracker ที่เราใส่ไว้

Topic: 

python: ตัวอย่างฟังก์ชั่น Info

อ่าน Dive Into Python เห็นตัวอย่างฟังก์ชั่น Info
เลยประยุกต์มาทำบนเว็บครับ

เผื่อจะขยายไปเป็น search help

Topic: 

python: ทำ syntax hightlight

ทดลองทำ syntax highlight โดยลอกจาก โมดูล GeSHiFilter ของ drupal ซึ่งเอามาจากโค๊ด PHP ที่ GeSHi อีกทีนึง แก้ปรับสี css นิดเดียว
ทดลองดูซอร์สได้ดังนี้

ตอนนี้ทำได้แค่ไพธอนภาษาเดียว และน่าจะยังมีบั๊กอยู่เยอะ จะค่อย ๆ ปรับปรุงไปเรื่อย ๆ ครับ

ยังไม่รู้ว่าโค๊ดของโมดูลหลัก dweb จะเปลี่ยนแปลงไปยังไงนะครับ แต่ตอนนี้โพสต์แบบนี้ไปก่อน

python: อ่านเนื้อความจากเว็บ

เราสามารถใช้ python อ่านเนื้อหาจากเว็บได้โดยใช้โมดุล urllib

เอาตัวอย่างจาก Dive into Python - 11.2. How not to fetch data over HTTP

>>> import urllib
>>> data = urllib.urlopen('http://diveintomark.org/xml/atom.xml').read()    1
>>> print data
<?xml version="1.0" encoding="iso-8859-1"?>
<feed version="0.3"
  xmlns="http://purl.org/atom/ns#"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xml:lang="en">
  <title mode="escaped">dive into mark</title>
  <link rel="alternate" type="text/html" href="http://diveintomark.org/"/>
  <-- rest of feed omitted for brevity -->

ด้วยวิธีนี้เราสามารถนำเข้าไฟล์สตรีมทั้งหลายได้โดยสะดวก

python: สร้างสคริปต์เก็บเนื้อหาเว็บเพจ

จากตอนก่อน เราสามารถนำมาสร้างสคริปต์ง่าย ๆ เอาไว้เก็บเนื้อหาของหน้าเว็บได้ดังนี้
$ vi d.getweb.py

#!/usr/bin/env python
# SAVE CONTENT OF WEB PAGE TO FILE
import sys, os, urllib

def usage(progname):
    print "Usage: %s URL FILENAME" % (progname)
    print "Save content of web page to file."


def cannotopenfile(filename="",readwrite="r"):
    if readwrite=="r":
        msg=" reading"
    else:
        msg=" writing"

    print "Cannot open file %s for %s." % (filename, readwrite)


def genfilename(filename="",ext="new"):
    if filename=="":
        return ""
    if ext.lower()!="new" and ext.lower()!="bak":
        ext="bak"
    if os.path.exists(filename+"."+ext):
        i=0
        while os.path.exists(filename+"."+ext+str(i)) and (i < 1000):
            i=i+1
        if i>999:
            return ""
        return filename+"."+ext+str(i)
    else:
        return filename+"."+ext
    #

if __name__=="__main__":
    progname=os.path.basename(sys.argv[0])
    try:
        url=sys.argv[1]
        filename=sys.argv[2]
    except:
        usage(progname)
        sys.exit(1)
    #
    try:
        if os.path.exists(filename):
            bakfile=genfilename(filename,"bak")
            os.rename(filename,bakfile)
    except: 
        cannotopenfile(filename,"w")
        sys.exit(1)
    #   
    try:
        data=urllib.urlopen(url).read()
    except:
        print "Cannot open %s." % (url)
        sys.exit(1)
    #   
    f=open(filename,"w")
    f.write(data)
    f.close()
    print "Save %s to %s success." % (url, filename)

เรียกใช้งานด้วยคำสั่ง
./d.getweb.py http://WEB.TO.GET FILENAME.EXT

python: แสดงซอร์สโค๊ดด้วย demo_source.py

จากครั้งก่อน ที่ทำตัวแจงเมธอด ขยายมาเป็นตัวค้นหาและแสดงซอร์สโค๊ด
โดยใช้พร๊อพเพอตี้ __file__

ปกติเราดูซอร์สได้เองอยู่แล้ว แต่การนำมาลงเว็บให้ค้นได้ง่าย ๆ อาจช่วยทำให้เข้าใจการทำงานของโมดูลในไพธอนดียิ่งขึ้นครับ