8

แก้ปัญหาเล็กๆ น้อยๆ กับ Pylons + mod_wsgi + virtualenv

เดิมที่ผมมีปัญหาว่า app ที่ใช้ pylons เขียนใช้ได้บ้างไม่ได้บ้าง ชนิดที่ว่าเข้าครั้งแรกไม่ได้พอ reload ก็ใช้ได้ เป็นแบบนี้ไปเรื่อยๆ โดยไม่รู้ว่าเกิดจากอะไรกันแน่. แต่เท่าที่ดู error log ของ Apache พอว่าเกิดจากหา package ไปเจอ. ผมก็ลองแก้ไปแบบชนิดที่ว่าคิดอะไรออกก็ลองดูหมด จนผ่านไปหลายชั่วโมง. สิ่งที่ทำคือ แทนที่จะเพิ่ม path เข้าไปใน app ที่วางไว้เฉยๆ โดยไม่ได้ install เช่น ผมเอา app ชื่อ basa ไปวางไว้ใน home ก็จะอยู่ที่ /home/vee/basa ผมก็เพิ่ม /home/vee เข้าไปใน python path เลย โดย site.addsitedir(‘/home/vee’) แต่ก่อนหน้านั้นก็ site.addsitedir(‘/home/vee/env/PYLONS/lib/python2.5/site-packages’) ไปแล้ว. ตอนนี้เลยเปลี่ยนไปเรียก python setup.py build และ python setup.py install ก่อนก็จะทำให้ basa นี้ไปอยู่ใน path อย่าง /home/vee/env/PYLONS/lib/python2.5/site-packages เป็นต้น ก็ทำให้ add แค่ path เดียวคือ /home/vee/env/PYLONS/lib/python2.5/site-packages ก็พอ. ผลคือตอนนี้ยังไม่พบปัญหาอะไร app ใช้งานได้ปกติดี.

ปกติชาวบ้านเขาอาจจะ install กันแบบนี้อยู่แล้ว แต่ผมดันทำอะไรประหลาดเองหรือเปล่าก็ไม่รู้ … และไม่อยากรู้เท่าไหร่ ขอให้ app ทำงานเนียนๆ ก็พึงพอใจมากแล้ว ^_^.

0

What I did for pylons app deployment.

I try to install my application created on Pylons on the Debian server that has already Apache2 + mod_wsgi + virtualenv + userdir.

What I did:

  1. creating prod.ini by copying development.ini.
  2. Change sqlalchemy.url
  3. set debug = false
  4. write a script in ~/public_html/wsgi-script as follow:
    import os
    import site
    os.environ['PYTHON_EGG_CACHE'] = "/home/myhome/egg"
    site.addsitedir("/home/myhome/wsgiapp/basa2")
    site.addsitedir("/home/myhome/pyenv/PYLONS-1/lib/python2.5/site-packages")
    
    from paste.deploy import loadapp
    APP_CONFIG = "/home/myhome/wsgiapp/basa2/prod.ini"
    application = loadapp("config:" + APP_CONFIG)
    
    
  5. I also modify this file: /home/vee/pydev/PYLONS-1/lib/python2.5/site-packages/Pylons-0.9.7rc3-py2.5.egg/pylons/wsgiapp.py by checking before the command:
    del  environ['pylons.pylons']

    following this changeset. (I use Pylons 0.9.7rc3)

The procedures above are just conclusion. I did a lot of trial and error. I also restart Apache web server (I must not have to do). By the ways, it works now.

0

xmlrpc ด้วย python บน apache

xmlrpc ด้วย python บน apache ผ่าน mod_wsgi. ใช้ xmlrpc บน python เขียนง่ายมากเลย ทั้ง client และ server ดูตัวอย่างจาก http://docs.python.org/library/simplexmlrpcserver.html ได้

แต่ว่า simple server นี้เป็น standalone server แล้วผมก็เจอปัญหาอีกว่า พอเรียกใช้จากเครื่องอื่น ที่ไม่ใช่เครื่องเดียวกันแล้วมั้นช้าๆ ชอบกล เลยเปลี่ยนไปใช้ wsgi-xmlrpc แทน มีคนเขียนไว้ให้แล้วด้วยดีจัง ^_^.

ทีแรกผมก็ลงโปรแกรมจาก easy_install เลย ใช้ easy_install wsgi_xmlrpc อะไรทำนองนี้ก็ลงได้ แต่เล่นไปเล่นมาเจอปัญหาภาษาไทย ก็เลยเอา source code จาก svn trunk ที่ google code มาใช้แทน ถึงตอนนี้ก็ยังใช้ได้ดีอยู่. (วิธีใช้ mod_wsgi กับ userdir เข้าไปดูที่ http://blog.vee-u.com/2008/06/18/mod_wsgi_userdir_ubuntu/ ได้
และ http://blog.vee-u.com/tag/wsgi/ ได้)

เพื่อที่ผมจะได้เอาไว้ดูเองในภายหลังด้วยจึงต้อง post ตัวอย่างสักหน่อย สมมุติ เขียน client แบบนี้

# -*- coding: UTF-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

from xmlrpclib import ServerProxy
server = ServerProxy("http://localhost/test_service.wsgi", encoding="UTF-8")
print server.test_func("ดีจ๊ะ")

พอโปรแกรมทำงานแล้วได้ผลแบบนี้

ดีจ๊ะ ^_^

เวลาเขียน server ก็เขียนประมาณนี้ใน test_service.wsgi

import site
import os

os.environ['PYTHON_EGG_CACHE'] = "/somewhere/egg"
site.addsitedir("/home/vee/pyenv/WSGI-1/lib/python2.5/site-packages")

from wsgiref import simple_server
import wsgi_xmlrpc

def test_func(txt):
   return txt + " ^_^"

application = wsgi_xmlrpc.WSGIXMLRPCApplication(methods=[test_func])

^_^

0

แยก python environment: Pylons + virtualenv + mod_wsgi

ในเครื่องแม่ข่ายเครื่องหนึ่งอาจจะเป็นไปได้ว่ามีคนใช้ Pylons, Django, Turbogears แถมยังอาจจะใช้ package ของ Python ที่แตกต่างๆ กัน. ถ้าลงทุก package ที่ทุกคนต้องการไว้ในส่วนกลางหมดก็เป็นไปได้ว่าอาจจะมีบาง package ขัดแย้งกัน โดยเฉพาะโปรแกรมเดียวกันที่ต่าง version กัน. มากไปกว่านั้นก็อาจจะต้องกวนให้ sys admin ช่วย install ให้บ่อยๆ ด้วย หรือจะให้ทุกคนลง package ในส่วนกลางได้เองหมด ก็อาจจะกระทบกับเสถียรภาพโดยรวมของระบบ. อย่ากระนั้นเลยใช้ virtualenv มาแยก Python environment ของแต่ละคนเลยดีกว่า.

ผมก็เลยลองลง virtualenv ใช้กับ Apache + mod_wsgi + mod_userdir บน Ubuntu 8.04 บนเครื่องส่วนตัวของผมเองดู. ใน entry นี้ผมสมมุติว่าใช้ Apache + mod_wsgi + mod_userdir ได้อยู่แล้วนะครับ (และ มี setuptools ไว้แล้ว) แต่ถ้าสนใจเรื่องการติดตั้งระบบที่ใช้ mod_wsgi ผมก็เขียนเก็บไว้บ้างเหมือนกันที http://blog.vee-u.com/tag/mod_wsgi/

ลง virtualenv ง่ายมากเพียงสั่ง

$ sudo easy_install virtualenv

ก็เสร็จแล้ว

จากนั้นก็สร้าง directory ไว้ลง package ส่วนตัว โดยสั่ง

$ mkdir $HOME/pyenv

จากนั้นก็เข้าไปจัดการสร้าง enviroment โดย

$ cd $HOME/pyenv
$ virtualenv –no-site-packages BASELINE

แล้วก็สร้าง environment สำหรับลง Pylons
$ virtualenv –no-site-packages PYLONS-1

ก่อนลง Pylons ก็ activate environment นั้นก่อน
$ source PYLONS-1/bin/activate

พอ activate แล้ว prompt จะเปลี่นนเป็น (PYLONS-1)$

จากนั้นก็ลง Pylons 0.9.7 (รุ่นทดลอง), SQLAlchemy 0.4.8 และ PasteDeploy (ไม่ต้อง sudo ด้วย)
(PYLONS-1)$ easy install pylons==0.9.7rc2
(PYLONS-1)$ easy install sqlalchemy==0.4.8
(PYLONS-1)$ easy install PasteDeploy

แล้วก็ไฟล์สำหรับเรียก Pylons จาก wsgi ประมาณนี้

APP_CONFIG = "/home/veer/Develop/pylons/ex1/production.ini"
import os
os.environ['PYTHON_EGG_CACHE'] = "/home/veer/egg"
import sys

# บอกให้ python ไปหา package ที่ที่เราเตรียมไว้
sys.path = []
sys.path.append("/home/veer/pyenv/BASELINE/lib/python2.5/site-packages")
sys.path.append("/home/veer/pyenv/PYLONS-1/lib/python2.5/site-packages")
sys.path.append("/home/veer/Develop/pylons/ex1")

from paste.deploy import loadapp
application = loadapp("config:" + APP_CONFIG)

อะไรที่เขียน /home/veer ต่างๆ นี้คือสิ่งที่ใช้ในเครื่องผม เครื่องอื่นๆ ก็คงใช้ต่างๆ กันไป

เท่านี้เว็บของแต่ละคนก็มี environment ของตัวเองแล้ว อย่างในกรณีนี้ package ต่างๆ ก็มาอยู่ใน $HOME ของแต่ละ user แทนที่จะไปอยู่รวมๆ กันใน /usr/lib ผู้ใช้แต่ละคนก็แก้ได้ สะดวกสบาย

อ้างอิง http://code.google.com/p/modwsgi/wiki/VirtualEnvironments

2

Pylons + mod_wsgi + mod_userdir

ต่อจาก ติดตั้ง Django ก็ต่อด้วย Pylons. ก่อนหน้าจะพยายามลง Pylons ผมก็ลองพวก WSGIDaemonProcess ไปแล้ว แต่ว่าไม่สำเร็จก็เลยข้ามๆ ไป. ใช้ user เป็น www-data ก็ได้ :-P.

Pylons ก็มา pattern เดิมๆ ที่อ่านมาจาก http://code.google.com/p/modwsgi/wiki/IntegrationWithPylons เริ่มด้วยสร้าง pylons.wsgi ใน /home/veer/public_html/wsgi-scripts ตามนี้

APP_CONFIG = "/home/veer/Develop/pylons/mydb4/production.ini"
import os
os.environ['PYTHON_EGG_CACHE'] = "/home/veer/egg"
import sys
sys.path.append("/home/veer/Develop/pylons/mydb4")
from paste.deploy import loadapp
application = loadapp("config:" + APP_CONFIG)

แล้วก็สร้าง /home/veer/egg เปลี่ยน permission ( mkdir /home/veer/egg; chmod 777 /home/veer/egg )

แล้วก็แก้สร้าง production.ini โดยการ copy มาจาก development.ini แล้วก็แก้ให้
full_stack = false
และ
debug = false

เท่านี้ก็น่าจะพอใช้ได้แล้ว

ลืมไปผมสร้าง app ไว้ใน /home/veer/Develop/mydb4 นะครับ พวก development.ini ก็อยู่ในนี้ล่ะ

1

Django + userdir + mod_wsgi

แน่นอนเป็นภาคต่อมาจาก Turbogears + userdir + mod_wsgi. Django ก็ใช้ท่าคล้ายๆ Turbogears เปลี่ยน prefix นิดๆ หน่อยก็ใช้ได้แล้ว

หลังจากศึกษาวิธีใช้จาก http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango ผมสร้าง django.wsgi ไว้ใน /home/veer/public_html/wsgi-scrips อีกเช่นเคย

import os, sys
sys.path.append('/home/veer/Develop/django/mysite') # site ของผมเก็บไว้ที่นี้
sys.path.append('/home/veer/Develop/django')
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'

import django.core.handlers.wsgi

application = django.core.handlers.wsgi.WSGIHandler()

ที่ลำบากนิดหน่อยคือพวก media ทั้งหลาย ผมก็ copy มาไว้ใน home เลย (ขนาดประมาณ 300KiB กว่าๆ)

cp -r /usr/share/python-support/python-django/django/contrib/admin/media/ /home/veer/public_html/django_admin_media

แล้วก็ไปแก้ settings.py ใน /home/veer/Develop/django/mysite นิดหน่อย แก้ ADMIN_MEDIA_PREFIX จากเท่ากับ ” เป็น ADMIN_MEDIA_PREFIX = ‘/~veer/django_admin_media/’

เท่านี้ก็ไปเปิดเว็บดูก็ใช้ได้ (ถ้าผมไม่ได้ลืมเขียนอะไรไปนะ)

พรุ่งนี้น่าจะได้ลอง Pylons กับ WSGIDaemonProcess username user=username อะไรทำนองนี้.

2

mod_wsgi + userdir + Turbogears

อาจจะดูคลั่งๆ หน่อยแต่ mod_wsgi + userdir + Turbogears ก็ใช้ได้แล้ว. ด้วยพื้นฐานจากการใช้ mod_wsgi+userdir , การใช้ mod_wsgi กับ Turbogears และ การใช้ mod_wsgi กับ Turbogears แบบ non-root-mount. ก็แทบจะไม่ต้องทำอะไรแล้ว :-P.

แค่ copy ไฟล์ tg.wsgi ที่เคยอยู่ใน /home/veer/tg/tgapp/apache ไปไว้ใน /home/veer/public_html/wsgi-scripts/ แล้วก็แก้ prod.cfg ใน /home/veer/tg/tgapp นิดหน่อยที่ server.webpath ให้เปลี่ยนเป็น server.webpath=”/~veer/wsgi-scripts/tg.wsgi” เท่านี้ก็ใช้ซะงั้น.

สำหรับ Turbogears แล้วสำคัญมาที่ต้องใช้ tg.url เวลาเขียน URL ไม่ใส่ URL เอาเองตรงๆ (แบบที่ผมเคยทำ) … ไม่งั้นเวลามา deploy แบบนี้ก็แก้กันอ้วก :-P.