บันทึกของวีร์ | Vee(r)'s Blog

มีนาคม 1, 2010

ใช้ swath จาก python

Filed under: 1 — ป้ายกำกับ:, , — वीर @ 3:34 pm

swath เป็นโปรแกรมตัดคำที่ดีโปรแกรมหนึ่ง เอา text อะไรยัดเข้าไปก็มักจะไม่เจ๊ง ไม่ต้องเขียนอะไรครอบมาก แต่ว่าบอกทีก็อยากใช้จาก python วีธีหลักที่จะเรียกใช้ ก็อาจจะสร้าง module ด้วย c++ ขึ้นมาเชื่อม swath กับ python วิธีแรกนี้โปรแกรมทำงานได้รวดเร็ว แต่ว่ามันเหนื่อยนะกว่าจะเสร็จ

ผมก็เลยใช้วิธีที่โปรแกรมทำงานช้าๆ แต่เขียนเสร็จเร็วแทน โดยเรียกผ่าน subprocess

import subprocess

def wordbreak(utxt):
    if not isinstance(utxt, unicode):
        raise TypeError, "wordbreak needs unicode"
    tis_txt = utxt.encode("CP874", 'replace')
    p = subprocess.Popen("swath", stdin = subprocess.PIPE, \
            stdout = subprocess.PIPE, close_fds = True)
    p.stdin.write(tis_txt)
    p.stdin.close()
    raw_output = p.stdout.read().decode("CP874", "replace")
    words = raw_output.split("|")
    p.stdout.close()
    return words

# Copyright (c) 2010 Vee Satayamas
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.

เวลาเรียกใช้ก็สั่ง wordbreak(u”ทดลองตัดคำ”) อะไรแบบนี้ได้ แล้ว wordbreak ก็จะ return list ของคำออกมา ผมใช้ python 2.5.x นะครับ

พฤศจิกายน 23, 2009

KUCut API

Filed under: 1 — ป้ายกำกับ:, , — वीर @ 4:07 pm

ตั้งแต่ version 1.2.7 เป็นต้นไป KUCut มี API ให้เรียกใช้ง่ายๆ จาก Python แล้ว เวลาเรียกใช้งานทำแบบนี้

from kucut import SimpleKucutWrapper as KUCut
myKUCut = KUCut()
result = myKUCut.tokenize([u"ทดสอบทดสอบ"])

ใน result ก็จะได้ list 3 ชั้นออกมา

มิถุนายน 28, 2009

python: สร้าง type ใหม่จาก function

Filed under: old posts — ป้ายกำกับ:, , — वीर @ 10:39 pm

ผมต้องการสร้าง function ที่เอาไว้สร้าง class อีกทีแบบ struct ใน ruby (ถ้าผมจำไม่ผิดนะครับ) ก็เลยใช้ function: type(name, bases, dict) มาช่วย จริงๆ แล้วผมก็ไม่รู้หรอกว่าเป็นท่าที่ควรทำหรือเปล่า แต่ก็เอามาโพสก่อน เพราะถ้างมอยู่คนเดียวโอกาสที่จะแก้ไขอะไรก็คงยาก

class DefaultDataModelBase(object):
    def __init__(self, **kwargs):
        for key in self.keys:
            if kwargs.has_key(key):
                self.__dict__[key] = kwargs[key]
            else:
                self.__dict__[key] = None

def defaultDataModel(*keys):
    return type("DefaultDataModel", (DefaultDataModelBase,), dict(keys = keys))

ก็ได้ defaultDataModel ออกมาคล้าย struct ล่ะ เวลาใช้ก็ใช้แบบนี้

Student = defaultDataModel('name', 'score')
a = Student(name="นาย ก.", score = 99.99)
print a.score

อะไรประมาณนี้ จริงๆ อยากจะใช้ namedtuple แต่ว่า Python 2.5 ไม่มีก็เลยลองทำแบบนี้ดู

มีนาคม 9, 2009

Python libthai binding (th_brk only)

Filed under: old posts — ป้ายกำกับ:, , , , , , — वीर @ 11:11 am

I want to use libthai from Python so I wrote this extension.

#include 
#include "structmember.h"
#include 

static PyObject*
th_brk_(PyObject *self, PyObject *args)
{
    PyObject *result = NULL;

    Py_UNICODE *s1;
    int s1_len;

    if (PyArg_ParseTuple(args, "u#", &s1, &s1_len)) {
        int *pos = (int *)malloc(sizeof(int) * (s1_len + 1));
        PyObject *txt_cp874 = PyUnicode_Encode(s1, s1_len, "CP874", NULL);
        Py_ssize_t len = PyString_Size(txt_cp874);
        char *c_txt_cp874 = PyString_AsString(txt_cp874);
        int n = th_brk((unsigned char *)c_txt_cp874, pos, len);
        int i, s = 0;
        char *buffer = (char *)malloc(sizeof(char) * (s1_len + 1));
        result = PyList_New(0);
        for(i = 0; i < n; i++) {
            PyObject *tok_cp874 = PySequence_GetSlice(txt_cp874, s, pos[i]);
            Py_ssize_t tok_len;
            PyObject *tok;
            PyString_AsStringAndSize(tok_cp874, &buffer, &tok_len);
            tok = PyUnicode_Decode(buffer, tok_len, "CP874", NULL);
            s = pos[i];
            PyList_Append(result, tok);
        }
        if(s < len) {
            PyObject *tok_cp874 = PySequence_GetSlice(txt_cp874, s, len);
            Py_ssize_t tok_len;
            PyObject *tok;
            PyString_AsStringAndSize(tok_cp874, &buffer, &tok_len);
            tok = PyUnicode_Decode(buffer, tok_len, "CP874", NULL);
            PyList_Append(result, tok);
        }
        free(pos);
    }
    return result;
}

static PyMethodDef module_methods[] = {
    {"th_brk", (PyCFunction)th_brk_, METH_VARARGS,
     "Thai word break"},
    {NULL, NULL, 0, NULL}   /* sentinel */
};

#ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
initlibthai(void)
{
    PyObject* m;
    m = Py_InitModule3("libthai", module_methods,
                       "libthai module");
    if (m == NULL)
      return;
}

มีนาคม 5, 2009

AuthKit + OpenID + MysqlStore

Filed under: old posts — ป้ายกำกับ:, , , , , , , , — वीर @ 2:05 pm

In previous examples, I always use file store, which I found that it is quite difficult to use when I deploy BasaAsa to the server so I change to use MySQL store. To use MySQL store, I modified websetup.py in order to create table for OpenID library.

websetup.py:

"""Setup the basaasa application"""
import logging

from basaasa.config.environment import load_environment
from basaasa.users.authkit_elixir_driver import UsersFromDatabase
from basaasa import model
from authkit.authenticate.open_id import make_store #added
from pylons import config #added

log = logging.getLogger(__name__)

def setup_app(command, conf, vars):
    """Place any commands to setup basaasa here"""
    load_environment(conf.global_conf, conf.local_conf)
    from elixir import metadata
    metadata.create_all(checkfirst=True)
    store_type = config.get('authkit.openid.store.type') #added
    stote_config = config.get('authkit.openid.store.config') #added
    conn, cstore = make_store(store_type, stote_config) #added
    if store_type == 'mysql': #added
        cstore.createTables() #added

Then after I run paster setup-app development.ini, tables for storing OpenID information have been created.

มีนาคม 4, 2009

มีนาคม 2, 2009

OpenID + AuthKit + Pylons (simple)

Filed under: old posts — ป้ายกำกับ:, , , , , , , , , — वीर @ 5:48 am

I try to post simple example how to use OpenID with AuthKit 0.4.3 and Pylons 0.9.7. by adapting example from AuthKit. So I just create new Pylons app named “topenid” and modify it as follow:

  1. development.ini:
    These lines below are added to development.ini

    authkit.setup.enable = true
    authkit.setup.method = openid, cookie
    authkit.openid.store.type = file
    authkit.openid.store.config =
    authkit.openid.charset = UTF-8
    authkit.openid.path.signedin = /auth/signin
    authkit.cookie.signoutpath = /auth/signout
    authkit.openid.store.baseurl = http://localhost:5000
    authkit.cookie.secret = somesecret
    
  2. midddleware
    ...
    import authkit.authenticate # this line is added
    ...
        app = PylonsApp()
        app = authkit.authenticate.middleware(app, app_conf) # this line is added
    ...
  3. topenid/controllers/auth.py
    import logging
    
    from pylons import request, response, session, tmpl_context as c
    from pylons.controllers.util import abort, redirect_to
    from authkit.permissions import RemoteUser
    from authkit.authorize.pylons_adaptors import authorize
    
    from topenid.lib.base import BaseController, render
    
    log = logging.getLogger(__name__)
    
    class AuthController(BaseController):
        def index(self):
            return 'Hello World'
    
        @authorize(RemoteUser())
        def test(self):
            return 'test'
    
        def signout(self):
            return 'signout'
    
        def signin(self):
            return 'signed in'

These are all modifications. I can access http://localhost:5000/auth/index as expect and http://localhost:5000/auth/test is redirected to an OpenID signin page. And I can sign out by visiting http://localhost:5000/auth/signout.

This example seems to work well but I need something more complex for example every user doesn’t have the same role. So I may post another more complex example soon.

กุมภาพันธ์ 15, 2009

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

Filed under: old posts — ป้ายกำกับ:, , , — वीर @ 2:27 pm

เดิมที่ผมมีปัญหาว่า 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 ทำงานเนียนๆ ก็พึงพอใจมากแล้ว ^_^.

มกราคม 30, 2009

KunyitTST: Taking list of string as key

Filed under: old posts — ป้ายกำกับ:, , , , , , — वीर @ 5:03 am

KunyitTst is a ternary search tree library in Python. Normally, it takes string or unicode as key since I use it for Thai word segmentation or something similar. By the way, now I want to use it to store list of string key too for storing (Moses) phrase table so it needs some modification. I’m still not sure how much it will effect performance. Anways, the patch is as follow:

Index: tests/test_basic.py
===================================================================
--- tests/test_basic.py	(revision 15)
+++ tests/test_basic.py	(working copy)
@@ -26,6 +26,27 @@
     def setup_method(self, method):
         self.setup()

+    def test_insert_has_key_list(self):
+        self.tst.insert(['i', 'have', 'a', 'key'], 10)
+        self.tst.insert(['i', 'have', 'a', 'book'], 20)
+        self.tst.insert(['a', 'book'], 30)
+        assert self.tst.has_key(['i', 'have', 'a', 'key']) == True
+        assert self.tst.has_key(['i', 'have', 'a', 'book']) == True
+        assert self.tst.has_key(['a', 'book']) == True
+        assert self.tst.has_key(['a', 'look']) == False
+
+    def test_iterator_list(self):
+        self.tst.insert(['a', 'book'], 30)
+        i = self.tst.iterator()
+        assert i.apply(u"a") == True
+        assert i.is_break_pos() == False
+        assert i.apply(u"book") == True
+        assert i.is_break_pos() == True
+        assert i.get_value() == 30
+
+        i = self.tst.iterator()
+        assert i.apply(u"book") == False
+
     def test_happy_insert(self):
         self.tst.insert(u"abc", 1)

Index: kunyittst/tst.py
===================================================================
--- kunyittst/tst.py	(revision 15)
+++ kunyittst/tst.py	(working copy)
@@ -27,7 +27,8 @@
         if not self._valid:
             return False
         if isinstance(ch, str) or isinstance(ch, unicode):
-            ch = ord(ch)
+            if len(ch) == 1:
+                ch = ord(ch)
         self._n = self._tst.goto_child(self._n)
         if self._n == None:
             return False
@@ -163,7 +164,10 @@
     def insert(self, k, v):
         p = self._root * Tst.SIZE
         for i, ch in enumerate(k):
-            c = ord(ch)
+            if len(ch) == 1:
+                c = ord(ch)
+            else:
+                c = ch
             while self._nodes[p + Tst.KEY] != c:
                 if self._nodes[p + Tst.KEY] == None:
                     self._nodes[p + Tst.KEY] = c

Reading phrase table (for Moses) using Python

Filed under: old posts — ป้ายกำกับ:, , , , , , , , — वीर @ 4:28 am

I’m going to analyze phrase table that is generated by Moses. So I have studied phrase table format from http://www.statmt.org/moses/?n=FactoredTraining.ScorePhrases and written a Python script for reading a phrase table into Python dict. The code is as follow.

import re

def _decode_tokens(field):
    return filter(lambda t: t != '', re.split(" ", field))

def _decode_link(link):
    m = re.match("\((.*)\)", link)
    if m:
        toks = filter(lambda l: l != '', re.split(",", m.group(1)))
        return map(lambda l: int(l), toks)
    else:
        raise RuntimeError

def _decode_links(field):
    links = filter(lambda t: t != '', re.split(" ", field))
    return map(_decode_link, links)

def _decode_num(field):
    toks = filter(lambda t: t != '', re.split(" ", field))
    return map(lambda tok: float(tok), toks)

def read_phrase_table(filename):
    NUM_FIELD = 5
    for i, line in enumerate(open(filename)):
        fields = re.split("\|\|\|", line.strip())
        if len(fields) != NUM_FIELD:
            raise RuntimeError
        phrase = {}
        phrase['source'] = _decode_tokens(fields[0])
        phrase['target'] = _decode_tokens(fields[1])
        phrase['links'] = _decode_links(fields[2])
        phrase['rev_links'] = _decode_links(fields[3])
        nums = _decode_num(fields[4])
        phrase['phrase_trans_prob'] = nums[0]
        phrase['lex_weight'] = nums[1]
        phrase['rev_phrase_trans_prob'] = nums[2]
        phrase['rev_lex_weight'] = nums[3]
        phrase['phrase_penalty'] = nums[4]
        yield phrase

def main():
    for phrase in read_phrase_table("phrase-table.0-0"):
        print phrase

if __name__ == '__main__':
    main()

เรื่องที่เก่ากว่า

Theme: Shocking Blue Green. บลอกที่ WordPress.com .

Follow

Get every new post delivered to your Inbox.

Join 632 other followers