機種依存文字

python機種依存文字*1が原因のエラーが発生。


python のエラーコードでは

UnicodeError: Shift_JIS decoding error: invalid character 0x8755

となっている。


回避方法についてあーだらこーだら考えたり検索してみたのだが、結局指定文字コードを変えれば良い模様。
というわけで対応文字コードを「Shift JIS (sjis)」から「Microsoft コードページ 932 (cp932)」に変更。
これで上手く動くようになった。


つーか、ファイル文字コード Shift JIS で機種依存文字使うなよ。
諸般の事情により変更は出来ないので、しょうがないが・・・。

参考ページ
http://d.hatena.ne.jp/itasuke/20061228#p1
Microsoft コードページ 932 (Wikipedia)
http://ja.wikipedia.org/wiki/Windows-31J

*1:具体的には「ローマ数字の2」

cpp : プリプロセッサを展開

仕事で障害解析。どうやら対象ソースのコンパイルオプションが期待したとおりに展開していない模様。
ひとまずどの様になっているか解析するのに cpp を使用した。

$ cpp 対象ファイル

で、プリプロセッサを展開したファイルを表示。
しかし、他のヘッダファイルに依存している部分が削除されていたので、
参照するヘッダファイルのパスを指定して展開。

$ cpp -I参照するヘッダファイルのパス 対象ファイル

これで、問題箇所のプリプロセッサの展開は完了。
案の定プリプロセッサの記述の問題だった。

popen 諸々

プロンプトから実行したコマンドの出力を受け取る popen という仕組みがある。
動作的にはコマンドをパイプした結果を受け取っていると考えればよい。

参考
http://www.python.jp/doc/2.4/lib/module-popen2.html

何故か popen2 モジュールと os モジュールの2箇所に分かれており、
微妙に引数・戻り値の順序が違ったりする。

  • popen2 モジュール
    • popen2
    • popen3
    • popen4
    • (class) Popen3
    • (class) Popen4
  • os モジュール
    • popen2
    • popen3
    • popen4

popen2, popen3, popen4

popen2/3/4 はそれぞれ取得できる実行結果によって異なる。

popen2
標準出力、標準入力
popen3
標準出力、標準入力、標準エラー出力
poepn4
(標準出力+標準エラー出力)、標準入力

以下に記述例を示す。

popen2 モジュール版

import popen2;

stdout, stdin = popen2.popen2( cmd [, bufsize [, mode ] ] );

stdout, stdin, stderr = popen2.popen3( cmd [, bufsize [, mode ] ] );

stdout_err, stdin = popen2.popen4( cmd [, bufsize [, mode ] ] );

os モジュール版

import os;

stdin, stdout = popen2.popen2( cmd [, mode [, bufsize ] ] );

stdin, stdout, stderr = popen2.popen3( cmd [, mode [, bufsize ] ] );

stdin, stdout_err = popen2.popen4( cmd [, mode [, bufsize ] ] );

引数

italic;">cmd:実行するコマンド。文字列で指定。
italic;">mode:データタイプ(バイナリ or テキスト)の指定。'b'、もしくは't'で指定。主に Windows で使用する場合に気にすること。
italic;">bufsize:子プロセスに対する入出力のバッファサイズ

戻り値

stdout
標準出力
stdin
標準入力
stderr
標準エラー出力
stdout_err
標準出力 + 標準エラー出力
popen2 モジュールと os モジュールでの違い

引数は「バッファサイズ」と「モード」の指定順序、戻り値は「標準入力」の指定位置が異なる。

  • popen2 モジュール
    • 引数の順序 : コマンド - バッファサイズ - モード
    • 戻り値の順序 : 標準出力 - 標準入力 - 標準エラー出力
  • os モジュール
    • 引数の順序 : コマンド - モード - バッファサイズ
    • 戻り値の順序 : 標準入力 - 標準入力 - 標準エラー出力

Popen クラス

popen2 モジュールには Popen3, Popen4 の2つのクラスがある。
通常の関数(popen2/3/4)との違いはコマンドの戻り値(実行結果)を受け取れるコマンドがあることにある。
通常の関数ではコマンド実行の成否判定は難しい為、
コマンド実行結果の成否をスクリプトの判定に使う場合は、Popen クラスを使った方が記述がシンプルになる。

コンストラク

Popen3

import popen2;

instance = popen2.Popen3( cmd [, capturestderr [, bufsize ] ] );

italic;">cmd:実行するコマンド。文字列で指定。
italic;">capturestderr:生成した子プロセスのエラー出力を受け取るかどうかの真偽値。デフォルト値は False 。
italic;">bufsize:子プロセスに対する入出力のバッファサイズ


Popen4

import popen2;

instance = popen2.Popen4( cmd [, bufsize ] );

引数については Popen3と同様。

メソッド

poll

ret = popen_inst.poll()

引数
(なし)
戻り値
子プロセスが実行中であれば -1 を終了していれば 0 を返す。


wait

ret = popen_inst.wait()

引数
(なし)
戻り値
コマンド実行結果*1を返す。値については os モジュールに記述されている。
属性
fromchild
子プロセスからの出力。ファイルオブジェクト。
tochild
子プロセスに対する入力。ファイルオブジェクト。
childerr
Popen3の引数 capturestderr が True ならばエラー出力が記録される。Popen4 ならば常に None。ファイルオブジェクト
pid
子プロセスのプロセスID

*1:正常終了、もしくは exit で終了やシグナルで終了

Template

Python の version 2.4 から Template という仕組みが追加されている(stringモジュール内)。

Template とは以前からある %*1 による置き換えではなく、
辞書型(dict)のキー、もしくは辞書に類似した仕組みを要素として使った置き換えをする仕組みである。

プレースホルダ

Template の仕組みを使って置き換える対象となる文字列のことです。IDとも言います。
プレースホルダ名には以下のルールがあります。

  • プレースホルダ名の開始は"$"で示される。
  • 先頭文字は以下の何れかで構成されていること。
    • アンダースコア(_)
    • 英小文字*2
  • 2文字目以降の文字列は以下の何れかで構成されていること。
    • アンダースコア(_)
    • 英小文字
    • 数字
  • プレースホルダ名の終端は以下の何れかで判定する。
    • プレースホルダ名が {} で囲まれている場合は、} が終端を示す。
    • {} で囲まれていない場合、プレースホルダ名の構成ルールに当てはまらない文字の直前を終端とする。
プレースホルダ名 : 例
プレースホルダ 可否
$data
$sum_sold
$_name
$Sample
$/src/ ×
$(dst) ×


$name をIDとして使う場合

プレースホルダ + 文字列 可否
data$name
$name's book
$nametype ×
${name}type

substitute と safe_substitute

Template クラスでは substitute と safe_substitute という2つのメソッドを持つ。

Template_Instance.substitute( dictionary )
Template_Instance.safe_substitute( dictionary )

italic;">Template_Instance:Templateクラスのインスタンス
italic;">dictionary:プレースホルダ名をキーに持つ辞書型(もしくは辞書に類似した要素)


2つのメソッドの違いはプレースホルダを置き換えられなかった場合の動作の違いです。

プレースホルダを置き換えられない場合
substitute, safe_substitute の引数のデータ内にプレースホルダ名をキーに持つ要素が無い場合のこと。
  • substitute の場合、ValueError の例外を raise します。
  • safe_substitute の場合、プレースホルダ名がそのまま使用します。

サンプルコード

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

import string;

tmp = string.Template( "I'm ${name}.  I'm from ${country}." );

print tmp.substitute( { 'name': 'NelNal', 'country': 'Tokyo' } );
print tmp.substitute( { 'name': 'Chan', 'country': 'China' } );
print tmp.substitute( name='Tom', country='America' );

*1:"print (This is %s) % 'pen'" の様な置き換え

*2:Templateクラスを使ってみた範囲では英大文字も使えるようだが

文字列から文字を除去

rstrip

rstrip は文字列右から指定文字を除去するメソッド。

string.rstrip( [ chars ] )

italic;">chars:除去したい文字の集合。文字列型で指定すること。

引数を指定しない場合は

  • \t
  • \n
  • \r
  • \v*1
  • \f*2

が除去する文字として扱われる。

サンプルコード

以下の方法は改行コード(win = \r\n, mac = \r, unix = \n)を意識せずに改行を除去して、
実行環境の改行コードで出力(標準出力)する方法。

fh = open("test.txt", "r")

lines = fh.readlines("")
for line in fh.readlines:
    print line.rstrip();

fh.close();

lstrip

lstrip は文字列左から指定文字を除去するメソッド。

string.lstrip( [ chars ] )

引数の使い方は rstrip と同様。

引数が省略された場合は空白文字が除去される。

strip

strip は文字列左右から指定文字を除去するメソッド。

string.strip( [ chars ] )

引数の使い方は rstrip, lstrip と同じ。

引数が省略された場合は空白文字が除去される。

dedent

dedent はインデントを除去するメソッド。
textwrap モジュールに含まれる。

import textwrap
ret = textwrap.dedent( string )

italic;">string:インデントを除去したい文字列
italic;">(return):インデントを除去した文字列
サンプルコード

三重引用符のインデントを除去

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

import textwrap

def test():
    str = """\
    Hello, 
    world!""";
    print str;
    print "-" * 8;
    print textwrap.dedent( str );

if __name__ == '__main__':
    test();

*1:0x000B : 垂直タブ。

*2:0x000C : フォームフィード。紙送り、改行のこと。

簡単にモジュールの有無をチェック

  • c オプションを使って簡単なプログラムを走らせることができる。

それの転用


モジュールが存在する時

$ python -c "import sys"
$

何もメッセージが出なければ問題なし。
逆にメッセージが出るようだとモジュールはインストールされてません。
さっさと Cheese Shop 等に行ってインストールしましょう。


モジュールが存在しない時

$ python -c "import tekito"
Traceback (most recent call last):
File "", line 1, in ?
ImportError: No module named tekito
$

標準入出力の文字コードを変える

標準出力をファイルにリダイレクトする際に
ファイルの文字エンコードShift_JIS に設定するのに今までは以下の様に行っていた。

$ python script | nkf > output_file

しかし、これだと自分は良いのだが余りCUIに慣れていない人に
余計な操作をさせることになるので何とか変えたいなぁ・・・と思っていたら
以下の方法を見つけた

参考
http://osksn2.hep.sci.osaka-u.ac.jp/~taku/osx/python/encoding.html
import sys, codecs

sys.stdin  = codecs.getreader( 'euc_jp' )( sys.stdin );
sys.stdout = codecs.getwriter( 'shift_jis' )( sys.stdout );

文字コードについては Python Library Reference の Codecs の項を参照とのこと。