Home > Tags > Module

Module

Python: テキストファイルの行頭に行番号を追加

コマンドラインで指定されたテキストファイルの行頭に行番号を追加し、そのデータを新たなファイルに書き出すスクリプトです。

ソースコード

#!/usr/bin/python
# coding: UTF-8

import sys

argvs = sys.argv
argc = len(argvs)
if (argc != 3):
    print 'Usage: $ python %s target_file making_file' % argvs[0]
    quit()
f = open(argvs[1])
lines2 = f.readlines()
f.close()
nf = open(argvs[2], 'w')
i = 1
for line in lines2:
    nf.write('%3d: %s' % (i, line))
    i = i + 1
nf.close()

仮にこのソースコードをfile05a.pyというファイルで保存した場合、使用する際はプロンプトに以下のように打ち込みます。

実行結果

プロンプト

> python file05a.py file05a.py file05a-l.txt

この結果、生成されたファイルが下記になります。

file05a-l.txt

  1: #!/usr/bin/python
  2: # coding: UTF-8
  3:
  4: import sys
  5:
  6: argvs = sys.argv
  7: argc = len(argvs)
  8: if (argc != 3):
  9:     print 'Usage: $ python %s target_file making_file' % argvs[0]
 10:     quit()
 11: f = open(argvs[1])
 12: lines2 = f.readlines()
 13: f.close()
 14: nf = open(argvs[2], 'w')
 15: i = 1
 16: for line in lines2:
 17:     nf.write('%3d: %s' % (i, line))
 18:     i = i + 1
 19: nf.close()

Python: コマンドライン引数の取得 - sys.argv変数

コマンドラインで与える引数によってプログラムの挙動を変えたいという場面はよくあります。Python ではコマンドライン引数は sys モジュールの argv 属性に文字列を要素とするリストとして格納されています。そして、リストの先頭要素(sys.argv[0])はスクリプトファイル名となっています。

ソースコード

# coding: Shift_JIS

import sys # モジュール属性 argv を取得するため

argvs = sys.argv  # コマンドライン引数を格納したリストの取得
argc = len(argvs) # 引数の個数
# デバッグプリント
print argvs
print argc
print
if (argc != 2):   # 引数が足りない場合は、その旨を表示
    print 'Usage: # python %s filename' % argvs[0]
    quit()         # プログラムの終了

print 'The content of %s ...n' % argvs[1]
f = open(argvs[1])
line = f.readline() # 1行読み込む(改行文字も含まれる)
while line:
    print line
    line = f.readline()
f.close

text.txt

It is meaningless only to think my long further aims idly.
It is important to set my aims but at the same time I should confirm my present condition.
Unless I set the standard where I am in any level, I'll be puzzled about what I should do from now on.

実行結果

引数を指定しない場合

$ python argv01.py
['argv01.py']
1

Usage: # python SCRIPTNAME.py filename

引数を指定した場合

$ python argv01.py text.txt
['argv01.py', 'text.txt']
2

The content of text.txt ...

It is meaningless only to think my long further aims idly.

It is important to set my aims but at the same time I should confirm my present condition.

Unless I set the standard where I am in any level, I'll be puzzled about what I should do from now on.

リファレンス

Python: SQLiteにデータを格納、検索、出力 - pysqlite

レコードの検索や格納処理性能がオープンソースのDBで間に合う程度の問題であれば、積極的に使っていきたいです。それによって、他のロジックのコーディングに傾注できます。また、DBという共通のプラットフォームは複数言語から扱えますので、データの再利用がしやすいです。
さて、今回はPythonからSQLiteを扱うサンプル(pysqliteの使い方)を書いてみます。

ソースコード

# coding: UTF-8

from pysqlite2 import dbapi2 as sqlite

# データベースに接続(作成)
con = sqlite.connect('test1.db')
# テーブルの列要素: 名前、性別(male or female)、年齢
con.execute('CREATE TABLE people (name TEXT, sex TEXT, age INTEGER)')
# テストデータの挿入(1行はタプルで)
con.execute('INSERT INTO people VALUES ("Taro", "male", 22)')
con.execute('INSERT INTO people VALUES ("Hanako", "female", 38)')
con.execute('INSERT INTO people VALUES ("Ranka", "female", 17)')
con.execute('INSERT INTO people VALUES ("Ozuma", "male", 40)')
con.commit() # DBに反映

# データの検索
cur = con.execute('SELECT * FROM people')
# データの出力
print 'NAMEt  SEXt  AGE'
for row in cur:
    print '%-8s  %-6s  %2d' % row # 1行のデータ構造はタプル
con.close()

実行結果

NAME      SEX     AGE
Taro      male    22
Hanako    female  38
Ranka     female  17
Ozuma     male    40

ドキュメント

Magic Workstation にインポートするオリジナルカードの作成スクリプト

Magic Workstation(MWS)という対戦カードゲームMagic: The Gatheringが出来るソフトがありますが、その機能の一つにオリジナルカードのインポート機能があります。カードの作成方法はテキストファイルに規定の書式で書いていけばいいのですが、自動化できるところがありましたので、即席ですがスクリプトを書いてみました。
SpoilerMaker.py

使い方

コマンドラインの第1引数に後述に説明する書式で作成したファイル名、第2引数に変換した(MWS規定の書式)ファイルを書き込むファイル名を指定してください。

使用例

D:\pytmp>python SpoilerMaker.py sample_cards.txt converted_cards.txt
ファイル"sample_cards.txt"を読み込みます。
変換処理中...
変換処理が完了しました。
ファイル"converted_cards.txt"に変換データを保存しました。

機能

具体例を以って示しますと、以下のような書式のファイルをMWSの規定に合わせた書式に書き直します。

読み込むファイル(作成するもの) sample_cards.txt

CN Apothecary Initiate
CC W
MC W
TC Creature - Kithkin Cleric
PT 1/1
CT Whenever a player plays a white spell you may pay %1. If you do, you gain 1 life.
FT
AT
RA C
CA 1/3

CN Armored Ascension
CC W
MC 3W
TC Enchantment - Aura
PT
CT Enchant creature  Enchanted creature gets +1/+1 for each Plains you control and has flying.
FT
AT
RA U
CA 2/3

CN Ballynock Cohort
CC W
MC 2W
TC Creature - Kithkin Soldier
PT 2/2
CT First strike  Ballynock Cohort gets +1/+1 as long as you control another white creature.
FT A kithkin's worst enemy is solitude
AT Jesper Ejsing
RA C
CA 3/3

1枚のカードは空行で区切ります。行頭にCN, CC, MC, TC, PT, CT, FT, AT, RA, CAを書き、小スペースをあけて該当する属性を書きます。省略した項目は自動的に追加され、その項目の属性値は空文字で置換されます。ただし、カードナンバー(Card #:の欄に書くもの)は自動的に計算されたものが書き込まれます。

書き出すファイル書式(MWSデフォルト規定)

注:Webページ用に一部のタブ文字の数を調整しました。

Card Name:	Apothecary Initiate
Card Color:	W
Mana Cost:	W
Type & Class:	Creature - Kithkin Cleric
Pow/Tou:	1/1
Card Text:	Whenever a player plays a white spell you may pay %1. If you do, you gain 1 life.
Flavor Text:
Artist:
Rarity:	C
Card #:	1/3

Card Name:	Armored Ascension
Card Color:	W
Mana Cost:	3W
Type & Class:	Enchantment - Aura
Pow/Tou:
Card Text:	Enchant creature  Enchanted creature gets +1/+1 for each Plains you control and has flying.
Flavor Text:
Artist:
Rarity:	U
Card #:	2/3

Card Name:	Ballynock Cohort
Card Color:	W
Mana Cost:	2W
Type & Class:	Creature - Kithkin Soldier
Pow/Tou:	2/2
Card Text:	First strike  Ballynock Cohort gets +1/+1 as long as you control another white creature.
Flavor Text:	A kithkin's worst enemy is solitude
Artist:	Jesper Ejsing
Rarity:	C
Card #:	3/3

カード1枚のテンプレート

CN
CC
MC
TC
PT
CT
FT
AT
RA
CA

スクリプトを使用する利点

  1. 各項目が"CA"(Card Name項目)など2文字なので、打ち込みや修正が簡単。同時に、各項目の列が揃うので見栄えも良く管理しやすいかも。MWS側でも項目名は変更できますけれどね。
  2. カードナンバー(Card #:の欄に書くもの)を自動的に計算してくれます。読み込みファイルのナンバーが正しくなくてもOKです。カードを任意の場所に挿入できて管理が楽かも。

実装したい機能等がありましたらコメントやブクマコメント等で気軽にどうぞ。

一応コードを表示しておきます。

# coding: Shift_JIS

"""
Magic Work Station の Spoiler List 作成スクリプト
author  : Yukun
Edit    : 2008/6/23
GPLv2
"""

import sys

version = '0.1'

err_inv = 'SpoilerMaker\'s Error: Nonexistent key'
err_non = 'Nothing'
success = 'Normal'

class MagicCard:
    CN = 'Card Name:\t'
    CC = 'Card Color:\t'
    MC = 'Mana Cost:\t'
    TC = 'Type & Class:\t'
    PT = 'Pow/Tou:\t'
    CT = 'Card Text:\t'
    FT = 'Flavor Text:\t'
    AT = 'Artist:\t\t'
    RA = 'Rarity:\t\t'
    CA = 'Card #:\t\t'

    def __init__(self):
        self.flag = 0
        self.attr = [{'CN':MagicCard.CN},
                    {'CC':MagicCard.CC},
                    {'MC':MagicCard.MC},
                    {'TC':MagicCard.TC},
                    {'PT':MagicCard.PT},
                    {'CT':MagicCard.CT},
                    {'FT':MagicCard.FT},
                    {'AT':MagicCard.AT},
                    {'RA':MagicCard.RA},
                    {'CA':MagicCard.CA},
                    ]

    def set_attr(self, key, value):
        attr = self.attr
        for i in range(len(attr)):
            if (attr[i].get(key, err_non) != err_non):
                attr[i][key] = attr[i][key]+value
                self.flag = 1
                self.attr = attr
                return success
        return err_inv

    def __str__(self):
        attr = self.attr
        str = ''
        for i in range(len(attr)):
            for (k, v) in attr[i].items():
                str += '%s :: %s\n' % (k, v)
        return str

class SpoilerMaker:
    def __init__(self):
        self.cards = []
        self.card_num = 0
        self.line_num = 0

    def read(self, filename):
        f = open(filename)
        x = f.read()
        f.close()
        lines = x.split('\n')

        cards = self.cards
        card = MagicCard()
        card_num = self.card_num
        line_num = self.line_num

        for line in lines:
            line_num +=1
            if (line == ''):
                if (card.flag != 0):
                    cards.append(card)
                    card_num += 1
                    card = MagicCard()
            else:
                kv = line.split(' ', 1)
                if (len(kv) != 2):
                    print '  %d行目でエラーです。書式を確認してください。' % line_num
                    print '  処理を中断し、終了します。'
                    exit(1)
                s = card.set_attr(kv[0], kv[1])
                if (s != success):
                    print '  %d行目でエラーです。書式を確認してください。' % line_num
                    print '  %s :: \'%s\' at line %d' % (s, kv[0], line_num)
        self.card_num = card_num
        self.line_num = line_num
        self.cards = cards

    def write(self, filename):
        g = open(filename, 'w')
        cards = self.cards
        for i in range(len(cards)):
            attr = cards[i].attr
            for j in range(len(attr)):
                if (j == 9):
                    attr[j]['CA'] = '%s%d/%d' % (MagicCard.CA, i+1, self.card_num)
                g.write('%s\n' % attr[j].values()[0])
            g.write('\n')
        g.close()

    def __str__(self):
        cards = self.cards
        str = ''
        for i in range(len(cards)):
            attr = cards[i].attr
            for j in range(len(attr)):
                str += '%s\n' % attr[j].values()[0]
            str += '\n'
        return str

def _main():
    argv_list = sys.argv
    readfile  = argv_list[1]
    writefile = argv_list[2]

    s = SpoilerMaker()
    print 'ファイル\"%s\"を読み込みます。' % readfile
    print '変換処理中...'
    s.read(readfile)
    print '変換処理が完了しました。'
    s.write(writefile)
    print 'ファイル\"%s\"に変換データを保存しました。' % writefile

if __name__ == '__main__': _main()

lxmlのインストール方法

lxml とはXMLやHTMLを扱うPythonのライブラリの一つです。

lxml is the most feature-rich and easy-to-use library for working with XML and HTML in the Python language.
- lxmlの冒頭の文より

linux系OS(Fedoraなど)の場合

# yum python-lxml

も一つの手ですがバージョンが古いので、通常はeasy_install経由でlxmlをインストールします。

前段階として、easy_installをインストールするためにhttp://peak.telecommunity.com/dist/ez_setup.pyをダウンロードしてスーパーユーザで実行します。

# python ez_setup.py error: invalid Python installation: unable to open /usr/lib/python2.5/config/Makefile (No such file or directory)

上のようなエラーがでた場合はpython-develをインストールします。また、合わせてlxmlに必要なパッケージもインストールするには以下のようなコマンドを実行します。

# yum install python-devel libxml2* libxslt*

改めて、

# python ez_setup.py

完了後、easy_installコマンドが実行できるようになります。
lxmlのインストールは以下のコマンドを実行すればOKです。

# easy_install lxml

ライブラリの確認方法は、

$ python
>>> import lxml
>>> 

でエラーが出なければOKです。

Windowsの場合

Webアプリのデプロイ環境はLinux系だけれど、開発やテストの一部はWindows機で行いたいのでWindowsにeasy_installでインストールしようとしましたが、途中でエラーが出て中々上手くいきませんでした。

解決に時間が掛かりそうだったので、とりあえずPython Package Index : lxml 1.3.4のlxml-1.3.4.win32-py2.5.exeをダウンロード&インストールして済ませました。

参考にした記事

Page 1 of 212

Home > Tags > Module

バックナンバー
最近のコメント
最近のトラックバック
メタ情報

Return to page top