書いたエントリは、引っ込めれない。

 上記のエントリに対して、id:bonlife氏よりコメントを頂きました。
ありがとうございます。(実は、僕ひそかに氏のブログの購読者だったりします。)

 まさか、SOS団のカウンタよろしく、カウンタのほとんどを自分で
回しているようなブログにコメントが書かれるとは、思いもせず、
変な興奮状態に陥っています。

しかも、

期待してます。

と期待までして頂いた。


これはあれでしょうか?選択肢が、

1. ソースを読む
2. ソースを読む
3. ソースを読む

という状況なのでしょうか。

 そうですか。はい、頑張ります!!

Pythonモジュールのソースを読もうとしたら、C言語のソースにぶち当たった

 PythonのRandomモジュールのソースコードを読んでみようと思い立ち、
random.pyを開いたら、

import _random

と、_randomっていうモジュールが読み込まれていて、
これがRandomクラスの親クラスになっていた。


 はて、_random.pyってあったっけ?と思い、ディレクトリ内を探したんだけど
見つからなくて、ネットで情報収集してみたら、これって_random.soっていう
共有ファイルらしい。で、この_random.soが、どのソースから作られているかも
調べたら、_randommodule.cというC言語で書かれたソースファイルが、
それらしい。


...読むか。

Perlクックブックのお題をPythonで解いてみた その16

レシピ2.6 乱数を生成する

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import random

# 25 <= n <= 75 の乱数を1つ生成する

print random.randrange(25,75+1)
print random.randint(25,75)

# a から z までの文字から10個を無作為に抽出する
str = "abcdefghijklmnopqrstuvwxyz"
listStr = [ str[random.randrange(0,len(str))]  for n in range(10)]
print ''.join(listStr)
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from random import Random

# 25 <= n <= 75 の乱数を1つ生成する
rand = Random()
print rand.randrange(25,75+1)
print rand.randint(25,75)

# a から z までの文字から10個を無作為に抽出する
str = "abcdefghijklmnopqrstuvwxyz"
listStr = [ str[rand.randrange(0,len(str))]  for n in range(10)]
print ''.join(listStr)


 さて、上の2つ、結果として同じ処理を行っている訳ですが、
ソースコードが、微妙に違います。

違う部分というのは、モジュールのインポート部分。
上の方のインポート部分が、

import random

なのに対して、下のものは

from random import Random

となってします。
これは、どちらもrandomモジュール内のRandomクラスをインポートしています。

 randomモジュールには、Randomクラスの他にWichmannHillクラスと
SystemRandomクラスが定義されています。

 下のソースは、この中のRandomクラスをインポートすることを、
プログラマが明示的に書いている形になります。
では、上のソースは、どのような仕組みになっているのかというと、
randomモジュールの最後の方で、実はRandomクラスを用いてインスタンス
生成しているのです。

random.py Line 828

_inst = Random()
seed = _inst.seed
random = _inst.random
uniform = _inst.uniform
randint = _inst.randint
choice = _inst.choice
randrange = _inst.randrange
sample = _inst.sample
shuffle = _inst.shuffle
normalvariate = _inst.normalvariate
lognormvariate = _inst.lognormvariate
expovariate = _inst.expovariate
vonmisesvariate = _inst.vonmisesvariate
gammavariate = _inst.gammavariate
gauss = _inst.gauss
betavariate = _inst.betavariate
paretovariate = _inst.paretovariate
weibullvariate = _inst.weibullvariate
getstate = _inst.getstate
setstate = _inst.setstate
jumpahead = _inst.jumpahead
getrandbits = _inst.getrandbits

この部分があるので、プログラマは、Randomクラスを明示的にインポートして
インスタンスを作ることなく、メソッドをしようすることが可能なのです。


(偉そうに書いているけど、これ、リファレンスにも書いてあるという事実)

ブログとか作ってみたいかと その3.1

データベースの修正

Blobテーブル

 カテゴリ情報を追加しました。

class Blog(SQLObject):
    blog_name = UnicodeCol(length=32)
    description = UnicodeCol(length=128)
    user_id = ForeignKey('User')
    entries = MultipleJoin('Entry')
    Categories = MultipleJoin('Category')
Categoryテーブル

 ブログIDを追加しました。

class Category(SQLObject):
    category_name = UnicodeCol(unique=True,length=16)
    entris = RelatedJoin('Entry')
    blog_id = ForeignKey('Blog')

ブログとか作ってみたいかと その3

データベースの設定

 プロジェクトを作成したので、次に使用するデータベースの設定を行います。

 tgBlogディレクトリ配下にある「dev.cfg」ファイルを
編集することによって設定が可能となります。

 「dev.cfg」ファイルを開くと、以下のように書かれた箇所が見れます。

# DATABASE

# pick the form for your database
# sqlobject.dburi="postgres://username@hostname/databasename"
# sqlobject.dburi="mysql://username:password@hostname:port/databasename"
# sqlobject.dburi="sqlite:///file_name_and_path"

# If you have sqlite, here's a simple default to get you started
# in development
sqlobject.dburi="sqlite://%(current_dir_uri)s/devdata.sqlite"

 これをみると、PostgreSQLMySQLsqliteのうちいずれかが選択可能なようです。

また、デフォルトはsqliteであり、tgBlogディレクトリ配下に
devdata.sqliteという名前のファイルを作成するようになっています。

tgBlogでは、sqliteを用いて、またtgBlogディレクトリ配下に
データベース用のファイルを作成しようと考えているので、
特に設定を変更する必要もないのですが、ファイル名だけでも変更しておくことにします。

sqlobject.dburi="sqlite://%(current_dir_uri)s/devdata.sqlite"

コメントアウト

#sqlobject.dburi="sqlite://%(current_dir_uri)s/devdata.sqlite"

そして、

# sqlobject.dburi="sqlite:///file_name_and_path"

という部分のコメントをはずし、パスとファイル名を指定します。

sqlobject.dburi="sqlite:///home/hoge/python/tg/tgBlog/tgblog.db"

Modelの編集

 データベースの設定が終わったので、
次にデータベース上の各情報が保存されているテーブルと
やりとりを行うためのModelの編集を行います。

「tgBlog/tgblog」ディレクトリ配下にあるmodel.pyを編集します。

model.pyを開くと以下のようにコードが書かれてます。

from datetime import datetime
from turbogears.database import PackageHub
from sqlobject import *
from turbogears import identity

hub = PackageHub('tgblog')
__connection__ = hub

# class YourDataClass(SQLObject):
#     pass
・
・
・

・・・以降には、認証用の「Visitクラス」、「VisitIdentityクラス」、
「Groupクラス」、「Userクラス」、「Permissionクラス」が定義されています。

では、今回扱うそれぞれの情報について、クラスを宣言していきます。

ブログ情報
class Blog(SQLObject):
    blog_name = UnicodeCol(length=32)
    description = UnicodeCol(length=128)
    user_id = ForeignKey('User')
    entries = MultipleJoin('Entry')

 クラスは、SQLObjectを継承して作成します。
 Blogクラスには、ブログの名前、ブログの説明、所有するユーザを表すID、そのBlogに登録されたエントリについての4つの情報を定義します。

エントリ情報
class Entry(SQLObject):
    title = UnicodeCol(length=64)
    body  = UnicodeCol(length=2048)
    created = DateTimeCol(default=datetime.now)
    blog_id = ForeignKey('Blog')
    comments = MultipleJoin('Comment')
    categories = RelatedJoin('Category')

 Entryクラスには、エントリのタイトル、本文、作成日、エントリが登録されるブログのID、コメント、カテゴリについて定義します。

Comment情報
class Comment(SQLObject):
    user_name = UnicodeCol(length=32)
    title    = UnicodeCol(length=32)
    comment  = UnicodeCol(length=256)
    created  = DateTimeCol(default=datetime.now)
    entry_id = ForeignKey('Entry')

 Commentクラスには、コメントの投稿主の名前、タイトル、コメント本文
作成日、どのエントリに対してのコメントなのかの情報について定義します。

Category情報
class Category(SQLObject):
    category_name = UnicodeCol(unique=True,length=16)
    entris = RelatedJoin('Entry')

 Categoryクラスには、カテゴリ名と、各カテゴリが付いているエントリ情報に
ついて定義します。

テーブルの作成

 クラスを定義したら、テーブルを作成します。
 テーブルの作成は、tgBlogディレクトリで
以下のコマンドを入力することでできます。

$ tg-admin sql create

テーブルの作成が成功すると、以下のようなメッセージが出力されます。

Using database URI sqlite:///home/hoge/python/tg/tgBlog/tgblog.db

そして、

-rw-r--r-- 1 hoge hoge 23552 1027 23:10 tgblog.db

というファイルが作成されます。

テストデータの入力

 テストデータを入力するために、コマンドシェルを立ち上げます。
シェルを立ち上げるためには、「tg-admin」コマンドを「shell」オプションを付けて実行します。

$ tg-admin shell

すると、シェルが立ち上がります。

Python 2.4.3 (#1, Oct 23 2006, 14:19:47)
[GCC 4.1.1 20060525 (Red Hat 4.1.1-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(CustomShell)
>>>
ユーザ情報
User(user_name='hoge',email_address="hoge@hoge.com",display_name='hoge',password='hoge')
>>> u = User.get(1)
>>> u
>>> <User 1 user_name=u'hoge' email_address=u'hoge@hoge.com' display_name=u'hoge' password=u'hoge' created='datetime.datetime...)'>
ブログ情報
>>> Blog(blog_name='Test Blog',description='Test',user_id=1)
<Blog 1 blog_name=u'Test Blog' description=u'Test' user_id=1>
>>> b = Blog.get(1)
>>> b
<Blog 1 blog_name=u'Test Blog' description=u'Test' user_id=1>
カテゴリ情報
>>> Category(category_name='test')
<Category 1 category_name=u'test'>
>>> c = Category.get(1)
>>> c
<Category 1 category_name=u'test'>
エントリ情報
>>> Entry(title=u'test' body=u'test' created='datetime.datetime...)' blog_id=1)
<Entry 1 title=u'test' body=u'test' created='datetime.datetime...)' blog_id=1>
>>> e = Entry.get(1)
>>> e
<Entry 1 title=u'test' body=u'test' created='datetime.datetime...)' blog_id=1>

 カテゴリの追加

>>> e.addCategory(1)
>>> e.categories
[<Category 1 category_name=u'test'>]
コメント情報
>>> Comment(user_name='test',title='title_comment',comment="comment test",entry_id=1)
<Comment 1 user_name=u'test' title=u'title_comment' comment=u'comment test' created='datetime.datetime...)' entry_id=1>
>>> c = Comment.get(1)
>>> c
<Comment 1 user_name=u'test' title=u'title_comment' comment=u'comment test' created='datetime.datetime...)' entry_id=1>

Perlクックブックのお題をPythonで解いてみた その13

レシピ2.2 浮動小数点を丸める

#!/usr/bin/env python2.4
# -*- coding: utf-8 -*-

# 小数点第2位で丸め込み
fnum = 0.74
print "%.1f" % fnum

fnum = 0.75
print "%.1f" % fnum

結果

$ ./recipe22.py
0.7
0.8

ブログとか作ってみたいかと その2

プロジェクトの作成

PythonTurboGearsなど、開発に必要なものは
既にインストール済みなので、早速プロジェクトを生成する。

TurboGearsでプロジェクトを生成するには、
「tg-admin」コマンドを使用する。

$ tg-admin quickstart
Enter project name: tgBlog
Enter package name [tgblog]:
Do you need Identity (usernames/passwords) in this project? [no] yes

これで、ユーザ認証が可能なプロダクトが生成される。
以下のようなディレクトリができる。

drwxrwxr-x 4 hoge hoge   4096 1025 23:52 tgBlog

で、ディレクトリの中身をみると

-rw-rw-r-- 1 hoge hoge  122 1025 23:52 README.txt
-rw-rw-r-- 1 hoge hoge 1909 1025 23:52 dev.cfg
-rw-rw-r-- 1 hoge hoge 2589 1025 23:52 sample-prod.cfg
-rw-rw-r-- 1 hoge hoge 2117 1025 23:52 setup.py
-rw-rw-r-- 1 hoge hoge 1194 1025 23:52 setup.pyc
-rwxrw-r-- 1 hoge hoge  797 1025 23:52 start-tgblog.py
-rw-rw-r-- 1 hoge hoge  122 1025 23:52 test.cfg
drwxrwxr-x 2 hoge hoge 4096 1025 23:52 tgBlog.egg-info
drwxrwxr-x 7 hoge hoge 4096 1025 23:52 tgblog

Webアプリの雛型を立ち上げるには、以下のようにする。

$ ./start-tgblog.py

すると、びゃ〜と以下のようにログが出力され、
テスト用のサーバが立ち上がる。

2007-10-26 00:09:13,950 cherrypy.msg INFO CONFIG: Server parameters:
2007-10-26 00:09:13,951 cherrypy.msg INFO CONFIG:   server.environment: development
2007-10-26 00:09:13,951 cherrypy.msg INFO CONFIG:   server.log_to_screen: True
2007-10-26 00:09:13,951 cherrypy.msg INFO CONFIG:   server.log_file:
2007-10-26 00:09:13,952 cherrypy.msg INFO CONFIG:   server.log_tracebacks: True
2007-10-26 00:09:13,952 cherrypy.msg INFO CONFIG:   server.log_request_headers: True
2007-10-26 00:09:13,952 cherrypy.msg INFO CONFIG:   server.protocol_version: HTTP/1.0
2007-10-26 00:09:13,953 cherrypy.msg INFO CONFIG:   server.socket_host:
2007-10-26 00:09:13,953 cherrypy.msg INFO CONFIG:   server.socket_port: 8080
2007-10-26 00:09:13,954 cherrypy.msg INFO CONFIG:   server.socket_file:
2007-10-26 00:09:13,954 cherrypy.msg INFO CONFIG:   server.reverse_dns: False
2007-10-26 00:09:13,954 cherrypy.msg INFO CONFIG:   server.socket_queue_size: 5
2007-10-26 00:09:13,955 cherrypy.msg INFO CONFIG:   server.thread_pool: 10
2007-10-26 00:09:14,003 turbogears.visit INFO Visit Tracking starting
2007-10-26 00:09:14,036 turbogears.visit.sovisit INFO Succesfully loaded "tgblog.model.Visit"
2007-10-26 00:09:14,036 turbogears.visit INFO Visit filter initialised
2007-10-26 00:09:14,153 turbogears.identity INFO Identity starting
2007-10-26 00:09:14,195 turbogears.identity.soprovider INFO Succesfully loaded "tgblog.model.User"
2007-10-26 00:09:14,196 turbogears.identity.soprovider INFO Succesfully loaded "tgblog.model.Group"
2007-10-26 00:09:14,196 turbogears.identity.soprovider INFO Succesfully loaded "tgblog.model.Permission"
2007-10-26 00:09:14,197 turbogears.identity.soprovider INFO Succesfully loaded "tgblog.model.VisitIdentity"
2007-10-26 00:09:14,238 turbogears.identity INFO Identity visit plugin initialised
2007-10-26 00:09:14,242 turbogears.identity.soprovider INFO Succesfully loaded "tgblog.model.User"
2007-10-26 00:09:14,242 turbogears.identity.soprovider INFO Succesfully loaded "tgblog.model.Group"
2007-10-26 00:09:14,243 turbogears.identity.soprovider INFO Succesfully loaded "tgblog.model.Permission"
2007-10-26 00:09:14,243 turbogears.identity.soprovider INFO Succesfully loaded "tgblog.model.VisitIdentity"
2007-10-26 00:09:14,446 cherrypy.msg INFO HTTP: Serving HTTP on http://localhost:8080/