16

ใช้ swath จาก python

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 นะครับ

3

KUCut API

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

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

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

1

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

ผมต้องการสร้าง 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 ไม่มีก็เลยลองทำแบบนี้ดู

0

Python libthai binding (th_brk only)

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;
}
0

AuthKit + OpenID + MysqlStore

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.