hollyさんのwiki

標準じゃないやつ。python3.x系ではインストールできんやつがほとんど

対応状況

http://python3wos.appspot.com/
まあぼちぼち

mod_wsgi

apacheとwsgi applicationの連携。python packageではないが記載しておく

よく見ておくところ

細かい設定などは見ておく必要あり

設定例

apache2.2 + mod_wsgi + virtualenv + werkzeug な環境での設定
virtualenv
werkzeugが動く環境を作る
cd $WORKON_HOME
virtualenv --no-site-package --distribute develop 
cd develop
. bin/activate
pip install werkzeug
werkzeug
app.wsgi。werkzeugの例をそのままぱくる
#!/usr/bin/env python

# vim: fileencoding=utf-8

import os
import sys

## for auto activate(自分でactivateして動かす場合はこのコードは不要)
here = os.path.dirname(os.path.abspath(__file__))
virtualenv = os.path.join(here, 'bin/activate_this.py')
execfile(virtualenv, dict(__file__=virtualenv))

from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple

@Request.application
def application(request):
    return Response("Hello World!\n")

if __name__ == '__main__':
    run_simple('127.0.0.1', 5000, application, use_reloader=True)
apache + mod_wsgi
wsgi.confとか。名前は適当でいい。
<IfModule wsgi_module>

ServerName freebsd-develop.vbox.priv
WSGIPythonPath /path/to/.virtualenv/develop/lib/python2.7/site-packages
WSGIScriptAlias / /path/to/.virtualenv/develop/app.wsgi

<Directory /path/to/.virtualenv/develop>
    Order deny,allow
    Allow from all
</Directory>
</IfModule>

細かい制御を行えるようにするのなら、WSGIDaemonProcess Directiveを使うほうがよさそう。
NameVirtualHost *:80
<IfModule wsgi_module>

<Virtualhost *:80>
ServerName freebsd-develop.vbox.priv
# 本番環境ではoffのほうがいい
WSGIScriptReloading Off(
WSGIDaemonProcess yourapplication user=holly group=accounts processes=2 threads=5 python-path=/path/to/.virtualenv/develop/lib/python2.7/site-packages maximum-requests=1000 
WSGIScriptAlias / /path/to/.virtualenv/develop/app.wsgi

<Directory /path/to/.virtualenv/develop>
    WSGIProcessGroup yourapplication
    WSGIApplicationGroup %{GLOBAL}
    Order deny,allow
    Allow from all
</Directory>
</VirtualHost>
</IfModule>
この設定を行うとapacheの子プロセス2つがuserで指定したonwerのプロセスで、あとはthreadで設定した分が、その都度起動する。process/thread混合型。
その他

easy_install(setuptools)

cpanpとかcpanmみたいなやつ。よく使いそうなので書いておく

インストール

easy_install <pkg>
基本的にはこれでよい。
インストールされるファイルの場所を記録する
python setup.py installする時と同じ
easy_install <pkg> --record <filename>
version指定
指定バージョン
easy_install "<pkg> == 1.1"
指定バージョン以下
easy_install "<pkg> < 1.1"
とか。http://dsas.blog.klab.org/archives/51284317.htmlとかにもうちょい詳しく載っている

一覧

機能としてはないので
# $PYTHONLIB = /usr/lib/pythonx.x  自分でコンパイルしていれたのなら/usr/local/lib/pythonx.x
grep -E "\.egg$" $PYTHONLIB/site-packages/easy-install.pth
./pyflakes-0.4.0-py2.4.egg
./pip-0.8.1-py2.4.egg
./psycopg2-2.3.0_beta1-py2.4-linux-i686.egg
とすると一覧表示される

upgrade

# --upgradeもよい
easy_install -U <pkg>
なければインストールされる

uninstall

mで。例えばpipの場合
easy_install -m pip
Searching for pip
Best match: pip 0.8.1
Processing pip-0.8.1-py2.4.egg
Installing pip script to /usr/bin
Installing pip-2.4 script to /usr/bin

Using /usr/lib/python2.4/site-packages/pip-0.8.1-py2.4.egg

Because this distribution was installed --multi-version, before you can
import modules from this package in an application, you will need to
'import pkg_resources' and then use a 'require()' call similar to one of
these examples, in order to select the desired version:

    pkg_resources.require("pip")  # latest installed version
    pkg_resources.require("pip==0.8.1")  # this exact version
    pkg_resources.require("pip>=0.8.1")  # this version or higher

Processing dependencies for pip
これでインストール時の情報が表示されるので、$PYTHONLIB/site-packages/easy-install.pthから該当するパッケージのegg情報を削除する。あとはここに表示された関連するファイル(eggと実際にインストールされたファイルと)を削除すればよい。--record をインストール時に指定していた場合は指定したファイルにすべてインストールパスが記録されるので、
cat record.txt | xargs rm -fr
とすればよい

pip

easy_installより便利らしいのでこっちも覚えておく。使おうとするとpython3だとsyntax errorとでる
ここが詳しい。http://d.hatena.ne.jp/rudi/20110107/1294409385
パッケージ一覧
ちゃんとある
pip freeze
Flask==0.6.1
Jinja2==2.5.5
Werkzeug==0.6.2
distribute==0.6.14
wsgiref==0.1.2
インストール
依存モジュールもインストールしてくれるようだ
pip install pkg
バージョン指定する場合は
pip install "pkg==x.x.x"
x.x.xより上のバージョン(逆も可能)
pip install "pkg>x.x.x"
などのようにする
アップグレード
pip install <pkg> --upgrade
アンインストール
pip uninstall <pkg>
検索
pip search syslog
virtualenv
virtualenvとpipを組み合わせる場合は意識することはないが
# --environment でもよい
pip -E /path/to/virtualenv/sandbox install <pkg>
とするとvirtualenvで作成したsandboxにpackageをインストールすることができる

pyflakes

コマンドがインストールされる。たぶん直接pyflakesのライブラリ本体を扱うことはあまりないようだ
#!/usr/bin/python

import resource
import fcntl
import signal
from signal import SIGTERM, SIGINT
from resource import RUSAGE_SELF

def handler(sig, flame):
        print "SIGNAL[%i] received" % sig

signal.signal(SIGTERM, handler)
signal.signal(SIGINT, handler)

data = []

f = open("test.txt", mode="w")
fcntl.flock(f, fcntl.LOCK_EX)
for i in range(0, 10000):
    data.append("a" * i)
    f.write(str(i) + "\n")
f.close()
print resource.getrusage(RUSAGE_SELF)
こんなソースがあるとして
pyflakes getrusage.py
として何も表示されなければ、それで問題ない。例えば
#signal.signal(SIGTERM, handler)
#signal.signal(SIGINT, handler)
のようにはじめの例からコメントにした状態でpyflakesを実行すると
./getrusage.py:5: 'signal' imported but unused
./getrusage.py:6: 'SIGINT' imported but unused
./getrusage.py:6: 'SIGTERM' imported but unused
のように警告を出してくれる

supervisord

packageというよりはプロセス死活監視ツール。http://supervisord.org/ たぶんdaemontoolsのようなタイプだと思う。

psycopg2

postgres connector。これがメジャーかどうかわからん。http://initd.org/psycopg/

環境設定

とりあえず
DB
項目
DBtestdb
USERpostgres
PASSなし(ほんまは設定しとくべきだが、試しなんで)
HOSTlocalhost
PORT5432
createdb -E UTF-8 -U postgres testdb
TABLE
section
fieldtypeother
section_idserialprimary key
section_namevarchar(128)not null

member
fieldtypeother
member_idserialprimary key
first_namevarchar(128)not null
last_namevarchar(128)not null
ageintnot null
section_idintnot null references section (section_id) on delete restrict

SQL
create table section (
	section_id    serial primary key,
	section_name  varchar(128) not null
);

create table member (
	member_id  serial primary key,
	first_name  varchar(128) not null,
	last_name  varchar(128) not null,
	age        int not null,
	section_id int not null references section (section_id) on delete restrict
);

insert into section(section_name) values('developer');
insert into section(section_name) values('operation');
insert into section(section_name) values('marketing');
insert into section(section_name) values('management');

insert into member(first_name, last_name, age, section_id) values('kurt', 'cobain', 27, 1);
insert into member(first_name, last_name, age, section_id) values('king', 'buzzo', 43, 2);
insert into member(first_name, last_name, age, section_id) values('akiko', ' ', 31, 3);

# 確認
select
    m.member_id,
    trim(m.first_name || ' ' || m.last_name) as member_name,
    m.age,
    s.section_name
from
    member as m
    left join section as 
    s on m.section_id = s.section_id;
 member_id | member_name | age | section_name
-----------+-------------+-----+--------------
         1 | kurt cobain |  27 | developer
         2 | king buzzo  |  43 | operation
         3 | akiko       |  31 | marketing
(3 行)

使い方

とりあえず
select
#!/usr/bin/python
# vim: fileencoding=utf-8 expandtab
import psycopg2
import psycopg2.errorcodes as errorcodes

try:
    conn = psycopg2.connect(database="testdb", user="postgres", password="", host="localhost", port=5432)
except Exception, e:
    print("DB connection error")
    print(e)
else:
    try:
        try:
            cur = conn.cursor()
            sql = "select section_id, section_name from section"
            cur.execute(sql)
            for record in cur:
                print(record)
            cur.close()
        except Exception, e:
            print(e.pgerror)
            print(e.pgcode)
            print(errorcodes.lookup(e.pgcode))
    finally:
        conn.close()
結果は
(1, 'developer')
(2, 'operation')
(3, 'marketing')
(4, 'management')
insert
#!/usr/bin/python
# vim: fileencoding=utf-8 expandtab

import psycopg2
import psycopg2.errorcodes as errorcodes

try:
    conn = psycopg2.connect(database="testdb", user="postgres", password="", host="localhost", port=5432)
except Exception, e:
    print("DB connection error")
    print(e)
else:
    try:
        try:
            cur = conn.cursor()
            sql = "insert into member (first_name, last_name, age, section_id) values (%s, %s, %s, %s)"
            cur.execute(sql, ("foo", "bar", 56, 4))
            conn.commit()
            print("rowcount: %d" % (cur.rowcount))
            print("rownumber: %d" % (cur.rownumber))
            print("lastrowid: %d" % (cur.lastrowid))
            cur.close()
        except Exception, e:
            print(e.pgerror)
            print(e.pgcode)
            print(errorcodes.lookup(e.pgcode))
    finally:
        conn.close()
place holderは
sql = "insert into member (first_name, last_name, age, section_id) values (%(first_name)s, %(last_name)s, %(age)s, %(section_id)s)"
cur.execute(sql, {"first_name":"foo", "last_name":"bar", "age":56, "section_id":4})
に置き換えることも可

使い方その2

selectの結果をdictに変える
iterator or fetchallの結果をtupleからdictに変更する
import psycopg2.extras

cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
sql = "select section_id, section_name from section"
cur.execute(sql)
for record in cur:
    print("section_id:%(section_id)s section_name:%(section_name)s" % record)
cur.close()
文字コード設定
set_client_encoding
# conn = psycopg2.connection
conn.set_client_encoding("UTF-8")
トランザクションレベル
set_isolation_level
# conn = psycopg2.connection
import psycopg2.extensions
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_READ_COMMITTED)
ちなみにデフォルトは
# 1 = psycopg2.extensions.ISOLATION_LEVEL_READ_COMMITTED
print(conn.isolation_level)
conn.commit()なしで即時反映させる場合はpsycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMITだと思う
commit/rollback
try:
    cur = conn.cursor()
    sql = "insert into member (first_name, last_name, age, section_id) values (%s, %s, %s, %s)"
    records = (("foo1", "bar1", 11, 1), ("foo2", "bar2", 12, 2), ("foo3", "bar3", 81, 4))
    for record in records:
        cur.execute(sql, record)
    conn.commit()
    cur.close()
except Exception, e:
    conn.rollback()
    print(e.pgerror)
    print(e.pgcode)
    print(errorcodes.lookup(e.pgcode))
perlでいうDBI::st#prepareはないのか?
複数処理
↑の例ではloopでexecuteを実行しているが
try:
    cur = conn.cursor()
    sql = "insert into member (first_name, last_name, age, section_id) values (%s, %s, %s, %s)"
    records = (("foo1", "bar1", 11, 1), ("foo2", "bar2", 12, 2), ("foo3", "bar3", 81, 4))
    cur.executemany(sql, records)
    conn.commit()
    cur.close()
except Exception, e:
    conn.rollback()
    print(e.pgerror)
    print(e.pgcode)
    print(errorcodes.lookup(e.pgcode))
となる
last_insert_id
ないようだ。なので
sql1 = "insert into member (first_name, last_name, age, section_id) values (%s, %s, %s, %s)"
# 対象テーブルのsequenseから最後の値をとる
sql2 = "select last_value from member_member_id_seq"
cur.execute(sql1, ("foo", "bar", 56, 4))
cur.execute(sql2)
last_insert_id = cur.fetchone()[0]
nextvalを使って、自分でserial型を更新した場合は
sql1 = "insert into member (member_id, first_name, last_name, age, section_id) values (nextval('member_member_id_seq'), %s, %s, %s, %s)"
sql2 = "select currval('member_member_id_seq')"
cur.execute(sql1, ("foo", "bar", 56, 4))
cur.execute(sql2)
last_insert_id = cur.fetchone()[0]
もはやpsycopg2のねたでもなんでもないが。ほかにいいものはないものか
iterator以外の取得方法
fetchallとか
cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
sql = "select member_id, (first_name || ' ' || last_name) as member_name from member"
cur.execute(sql)
records = cur.fetchall()
for record in records:
    print("member_id:%(member_id)s member_name:%(member_name)s" % record)
cur.close()
fetchone, fetchmanyなどがある
quote
place holderでやったほうがいいと思うけど
from  psycopg2.extensions import QuotedString

s = "I'm kurt cobain"
print(QuotedString(s).getquoted())
QuotedStringではAsIsでもいいようだが違いがよくわからない
タグ

Wiki内検索

Menu

ここは自由に編集できるエリアです。

管理人/副管理人のみ編集できます