Index > Jython Howto
Sat, October 14, 2006

{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)をよく使うので、これを例に説明すると...

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 
 Twitter
follow me on Twitter
 Categories