{update:2006-10-19}
Jython Howto
MacOSXで大量のファイルを一括処理する場合に、わたしは、jythonを使っています。 Windowsと違って、MacOSXには標準でJavaVMが用意されているので、 その分、jythonを使えるようにするための準備が少ないのもうれしいです。
Jythonは、JavaVM上で動くPythonですが、 Pythonの利点を持ちながら、Javaのライブラリがそのまま使えるので、重宝しています。
Jythonのインストール
Version 2.1
Jythonのサイトから jython_21.class を ダウンロードしたら、 インストールしたいディレクトリにコピーして、以下のコマンドを実行するだけです。
$ java jython_21
わたしの場合は、$HOME/local/jython にインストールして使っているので、 このページの説明では、そのパスにjythonがインストールされていることを 前提に説明しています。
Jythonの実行
Jythonは対話的に使うこともできますが、 ファイルにコードを書いておいて、それを実行させるのが普通だと思います。
foo.py というコードがあれば、
$ ${HOME}/local/jython/jython foo.py
とします。
でも毎回フルパスでJythonを指定するのは面倒なのでパスを指定しておきます。 ${HOME}/.profileに以下の行を追加。
export PATH=$HOME/local/jython:$PATH
ターミナル,iTermで起動しなおせば、有効になります。
これで単に
$ jython foo.py
とすれば実行できるようになります。
追加のjarが必要な場合の実行方法
jythonコードを実行するときに、 追加のjarファイル(つまり外部ライブラリ)が必要な場合は、 jython foo.py とだけしてもうまくいかない。
たとえば、XMLの処理をする場合に、わたしは、 JDOM(jdom.jar)をよく使うので、これを例に説明すると...
- jdom.jar を使用するjythonコードは、foo.py
- jdom.jar は、${HOME}/mylib/jdom.jar にある
CLASSPATHに jdom.jarを追加設定してから実行します。
export CLASSPATH=$CLASSPATH:${HOME}/mylib/jdom.jar
jython foo.py
makeから実行したい場合は、 Makefileを以下のように書く。 all: export CLASSPATH=$CLASSPATH:${HOME}/mylib/jdom.jar;jython foo.py
printが文字化けする
Jythonでは、文字列を出力するには、以下のようにします。
str="ほげほげ"
print str
しかしMacOSXのターミナルでは、たいていの場合、出力される文字は、文字化けしてしまう。
(文字化けしなかったら幸運です。)
これを回避するには、コードを書いたファイルの文字エンコードと、
JavaVMのデフォルトの文字エンコードとターミナルの表示エンコードが
全部一致する必要があります。
ここでは、すべてEUCJPで統一して文字化けをさける方法を説明します。
ターミナルのエンコード指定
MacOSX標準のTerminal.appを使っている場合は、 {quote} ターミナル > ウインドウ設定 > ディスプレイ > 文字セットエンコーディング {quote} で、指定します。
コードの書いてあるファイルの文字エンコードをEUCJPに
foo.py にコードが書いてあるとすると、
$ nkf -e foo.py > tmp ; mv tmp foo.py
JavaVMの文字エンコード
たぶん、MacOSXのJavaVMのデフォルトのエンコードはShift_JISだと思いますが、 よくわからないので、デフォルトに頼らないで、 EUCJPに明示的に指定します。
import java.lang as lang
import java.io as io
str="ほげほげ"
print str
pw=io.PrintWriter( io.OutputStreamWriter(lang.System.out,"EUCJP") )
pw.println(str)
pw.close()
これで、文字化けを回避できました。(面倒ですね。)
これらストリーム処理をたくさん記述する場合は、
commons-ioを使います。
よく使う処理:ディレクトリ内の拡張子 .txt を持つファイルを列挙する
jythonをbashの代わりに使う場合、たびたび使うことになるイディオム。
import java.lang as lang
import java.io as io
class TextFileFilter(io.FileFilter):
def accept(self,file):
fname=file.getName()
return lang.String(fname).endsWith(".txt")
list=io.File("./").listFiles(TextFileFilter())
for file in list:
print file.name
よく使う処理:ファイルの拡張子だけ変更したい
foo.txt を処理して、 strong:foo.html に保存したい、ということがあります。
そんなときは、 reモジュールを使って置き換えします。
import re
file="foo.txt"
matchstr=re.compile("\.txt$")
htmlf=matchstr.sub(".html",file)
print htmlf
よく使う処理:特殊記号のエスケープ処理
ウェブページにコードを載せる場合、HTMLで使用できない < > などの特殊記号を エスケープする必要があります。 RSSフィードなどの生成時でもやはりエスケープが必要で、この手のコードは 手元にあると便利です。
import sys
import java.lang as lang
import java.io as io
false=0
true=1
def read(file):
sb=lang.StringBuffer()
br=io.BufferedReader(io.FileReader(file))
while(true):
line=br.readLine()
if line==None:
break
line=lang.String(line).replaceAll("&","&")
line=lang.String(line).replaceAll("<","<")
line=lang.String(line).replaceAll(">",">")
line=lang.String(line).replaceAll("\"",""")
sb.append(line)
sb.append(lang.System.getProperty("line.separator"))
br.close()
return sb.toString()
file=io.File(sys.argv[1])
text=read(file)
print text
このコードを、convert.py というファイル名で保存したら、 以下のように実行する。(結果はコンソールに標準出力されます。)
$ jython covert.py foo.txt