Ruby 0
全214件 (214件中 1-50件目)
Tkinter でも、見た目のよい GUI を作れる のあと、CustomTkinter を使って WordCloud を書き出すアプリを作ってみた。Janome ではじめるテキストマイニング など参考にした。出力結果Python をインストールしていない環境でも実行できるように、pyinstallerを使って EXE 化したのだが、"pyinstaller --onefile app.py" で EXE 化すると、実行時にエラーが出てしまう。FileNotFoundError: [Errno 2] No such file or directory:'C:\\Users\\kugutsu\\AppData\\Local\\Temp\\_MEI255482\\janome\\sysdic\\entries_compact0.py'いろいろ調べてみた結果、あれこれ考えるのは面倒なので、 --collect-all janome をつけて pyinstaller を実行してみたところ、エラーが出ずに実行できるようになった。ちなみに janome は、pure python の形態素解析器。MeCab だと、EXE化するときに組み込みが面倒なので、janome を使ってみた。よほど大きいファイルを扱うのでなければ、この用途では十分かなと。ちなみに、EXE化すると、対象ファイル選択するときに、initial_dir = os.path.abspath(os.path.dirname(__file__))のようなコードがあると、上記のエラーの中にある、Local\Temp\_MEI255482 のようなところから実際には開かれるのがちょっ面倒なところ。Python インタープリタから、.py ファイルを実行するのであれば、その .py ファイルがある場所がスタート地点となるのだが、EXE化するときには、明示的にどこかのフォルダーを指定してあげた方が使いやすいかな。ちなみに、対象のファイルは、word, excel, pdf, txt から読み込めるようにした。結構簡単にできるが、PDF ファイルの場合、単語の途中で切れてしまいがちだったりするので、そのあたり何とかしたいなとか思ったりする。
2024.04.08
コメント(0)
Python で GUI アプリを作りたいとき、お手軽に始められるのが Tkinter。でも、見栄え残念だったので、あまり使いたくなかった。wxPython の方が自然な見栄えにできるので、以前、しばらく使ってみていたのだが、2020-11-21 から 2022-08-07 にリリースがなかったから開発滞ってしまったのかなと使うのをあきらめた。今は、2023-06-07 wxPython 4.2.1 が最新で開発継続している。そんなわけで、pyQt か pySide でも覚えるかと思ったが、その気力もなかったので、 tkinter でいいかとなっていた。そんなとき、Tkinter でももう少しいい感じにできるということが分かったので、Tkinter で十分かなと思う今日この頃。バリバリのアプリを作るわけでもないので。本格的なアプリなら、pyQt か pySide を最初から覚えたほうがいいと思う。ソースは、codefirstio/tkinter-excel-appこれ以外にも、同じような仕組みのテーマが公開されている。Forest-ttk-themeAzure-ttk-themeSun-Valley-ttk-themeちなみに Azure-ttk-theme を使うと、こんな感じのものが作れる。他にも、omSchimansky/CustomTkinter や、ttkbootstrap のようなものもある。
2024.02.25
コメント(0)
Paulus Schoutsen さんの pychromecast を使うと、Chromecast に自分で Python で作ったプログラムから簡単に動画を飛ばして表示することができる。ちなみに、この方は、Open-source home automation platform running on Python 3 (https://home-assistant.io を開発されている方。Raspberry Pi を使っていつかはホームオートメーションにも挑戦したいが、なかなかそちらまでいかない。。。。pychromecast の使い方は簡単で、pip install pychromecast でインストールしたら、次のようにすればいい。まずは、Chromecast への接続を確認。import pychromecast# 複数の Chromecast を持っていると、複数出てくるが、# 1つしかなければ、1つだけ出てくる。pychromecast.get_chromecasts_as_dict().keys()['Dev', 'Living Room', 'Den', 'Bedroom']ここからは、'Living Room' と名付けられた Chromecast に表示することとして話を進める。from __future__ import print_functionimport timeimport pychromecast# キャストしたい動画の URL を指定する。# ローカルネットワーク上の HTTP サーバーも可。url_to_play = 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4'# MIMEタイプ を指定する。mime_type = 'video/mp4'# キャストの指定 "Living Room" を指定した。cast = pychromecast.get_chromecast(friendly_name="Living Room")# デバイスの準備ができるのを待つ。cast.wait()# メディアコントローラーオブジェクトを生成して、# .play_media で、指定のコンテンツを再生。mc = cast.media_controllermc.play_media(url_to_play, media_type)その他、デバイスや接続ステータスの状態等を確認したい場合は、print(cast.device)print(cast.status)# その他、再生、一時停止mc.pause()# 5秒待つtime.sleep(5)# 再生を開始するmc.play()# 再生中止mc.stop()MIMEタイプ と URL を指定したら、'image/jpeg' で JPEG 画像を表示することもできた。'text/html' で Web ページを表示しようとしたが、これは表示できなかった。何かすればいいのかもしれないが。とりあえず、簡単な導入まで。ちなみに、PCのブラウザのコンテンツをキャストしておいて、cast.status を表示すると、ちゃんと再生されているコンテンツの情報が表示された。
2016.01.10
コメント(0)
私が比較的よく訪れるサイトの一つにthe mouse vs. the pythonpython programming from the frontlinがある。Pythonプログラミングのヒントがいろいろ掲載されるので好きなサイト。今日は、Getting Your Screen Resolution with Pythonというのが載っていたのでやってみた。Using the Linux Command LineUsing PyGTKUsing wxPythonUsing TkinterUsing PySide / PyQtそれぞれの記述がある。いずれにせよ、下回りは、Windowsなら PyWin32 の win32api か ctypes 、Mac なら AppKit とか、プラットフォームに依存しているわけだが、上記のようなクロスプラットフォームな GUI のフレームを使うことによって吸収されるので、意識する必要はない。ちなみに、最初の Linux の例では、X Window 環境なら xrandr | grep '*' でコマンドの出力から '*' のある行を取り出して、最初の部分に解像度があるので、テキスト処理をしているというもの。コマンド出力をちょっと処理してというのを subprocess.Popen でパイプ処理してという類の参考になる。つまり、こんな感じ、あとでパイプ処理を他の用途に流用できるようにしてみた(1つコマンドを実行して、その結果を2つ目のコマンドで処理してのパターン)。import subprocessdef command2pipe(cmd1, cmd2): p = subprocess.Popen(cmd1, stdout=subprocess.PIPE) p2 = subprocess.Popen(cmd2, stdin=p.stdout, stdout=subprocess.PIPE) p.stdout.close() first_line, rest_lines = p2.communicate() return(first_line, rest_lines)if __name__ == '__main__': cmd1 = ['xrandr'] cmd2 = ['grep', '*'] resolution_string, junk = command2pipe(cmd1, cmd2) resolution = resolution_string.split()[0] width, height = resolution.split('x') mesg = "Resolution: %sx%s" % (width, height) print(mesg)というのはさておき、それぞれの例をやってみたが、Linux 上では問題なく動いた。 Windows 10 上でも Linux のは別として、すべて問題なく動いた。クロスプラットフォームではなく Windows 上だけで動くことを前提であれば、Win32api や ctypes で呼び出した方が、読み込み時間が少ないので速い。from win32api import GetSystemMetricsprint "Width =", GetSystemMetrics(0)print "Height =", GetSystemMetrics(1)か、もっと最低限の読み込みだと、import ctypesuser32 = ctypes.windll.user32screensize = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)How do I get monitor resolution in Python? を見ると、もうちょっと、正確にやるにはどうしたらよいかというのも色々議論がある。例えば、Windows 上で DPI やデスクトップスケーリングを考慮した場合にはどうなるとか。(dpi_and_the_desktop_scaling_factor)。ところで複数のモニターとか接続してたらどうなるのか。あれこれ考慮し始めると面倒なことになる。なので、先人の成果をいただいて、pip install screeninfofrom screeninfo import get_monitorsfor m in get_monitors(): print(str(m))でよいかと。すばらしい。
2015.08.21
コメント(0)
Pascal van Kooten さんの yagmail (Yet Another GMAIL client) を使ってみた。インストールpip install yagmail~/.yagmail にアカウント名だけ1行入力しておき、メールを送信してみる。import yagmailyag = yagmail.SMTP()contents = ['This is the body, and here is just text http://somedomain/image.png', 'You can find an audio file attached.', '/local/path/song.mp3']yag.send('to@someone.com', 'subject', contents) そうすると、パスワードを入力できるのだが、入力しても、smtplib.SMTPAuthenticationError: (534, '5.7.9 Application-specific password required. Learn more at\n5.7.9 https://support.google.com/accounts/answer/185833 jdddddddddddddd.96 - gsmtp')のようなエラーが表示されてメールを送信できない。アプリ パスワードでログインのページを参照する。2 段階認証プロセスを使用してあるアカウントから送信したので、このエラーとなったと分かる。Google のアプリパスワードを設定してやり、表示されたコードをパスワードに設定すると、メールが送信できるようになった。まずは、アプリパスワードを生成して、上記のコードの一部をyag = yagmail.SMTP('GMAILのアカウント', 'アプリパスワード')と書き換えてメールを送信すると、送信成功。そのままスクリプトの中に入れておくのは、よろしくないので、keyring に登録し直す。yagmail.register('GMAIL のアカウント', 'アプリパスワード')を実行して、keyring に登録し直す。これで、設定スクリプトは削除して、最初のスクリプトでメールが送信できるようになった。HTML メールも、画像の添付も簡単なので便利。yagmail の使い方。yagmail 素敵。スクリプトから生のパスワードを追い出すには、keyringを使うのがいいなと改めて認識。次のページも参照。python:keyringによるパスワード管理スクリプトから生パスワードを追い出す
2015.08.06
コメント(3)
以前、Python のファイル参照や操作は面倒だというあなたに path モジュール という記事を書いた。標準ライブラリの os.path はイマイチ使いにくい。Python を使ってディレクトリやファイルをたどりながら何かするのは面倒。たとえば、このディレクトリの下のファイル名が「~」で終わっているファイルを削除したいとかいうのを書こうとすると、unix だったら find コマンドを使って、find . -name \*~ -print -exec rm {} \; とかあるわけで、そんな風にもっと簡単にできないかなぁと思う人も多いだろう。で、path モジュールを使えば、この手のものも簡単に書けるようになる。path だと、import pathd = '/var/apache/htdocs'for f in d.walkfiles('*~'): f.removeのような書き方ができた。ちなみに、os.path (python 2) を見ると os.path.walk があるが os.path (python 3) にはない。os.walk が残っている。python 3 では、pathlib — オブジェクト指向のファイルシステムパス が追加されているが、やっぱりもっと直感的に使えるようなものが欲しい。そこで、pyfs の登場となる。"pip install pyfs" でインストール。import fstarget_path = /var/apache/htdocs# 一ファイルずつ削除for f in fs.find('*~', target_path): fs.rm(f)# あるいは、まとめて削除to_delete = fs.find('*~', target_path)fs.rmfiles( to_delete )path や pathlib のようにファイルパスをオブジェクトとして、それを使って操作するという感じではなく、直接的に UNIX のコマンドのような感じで操作できる。ということで、気に入ってしまった。ソースを見てみればわかるが、かなりの部分が os.path や os をラップしているだけなので、基本を覚えるのは簡単。fs.exists(path) : os.path.exists(path)fs.isfile(path) : os.path.isfile(path)fs.rename(oldPath, NewPath, **kwargs) : os.rename(oldPath, newPath, **kwargs)fs.chdir(path, **kwargs) : os.chdir(path, **kwargs)fs.stat(path) : os.stat(path)fs.ctime(path) : os.stat(path).st_ctimefs.atime(path) : os.stat(path).st_atimefs.mtime(path) : os.stat(path).st_mtimefs.abspath(path, **kwargs) : os.path.abspath(path, **kwargs)fs.normalize(path, **kwargs) : os.path.normpath(path, **kwargs)fs.rm(path, **kwargs) : os.unlink(path, **kwargs)fs.unlink(*args, **kwargs) : os.unlink(path, **kwargs)fs.rmdir(path, recursive=True, **kwargs) : shutil.rmtree(path, **kwargs)fs.rmfiles(paths, **kwargs) : os.unlink(path, **kwargs)fs.exists(path, **kwargs) : os.path.exists(path, **kwargs)fs.cwd() : os.getcwd()fs.basename(path, ext="") : os.path.basename(path).replace(ext, "")fs.dirname(path) : os.path.dirname(path)fs.sep : os.path.sepこれらに加えて、fs.truncate(path, **kwargs) : path 以下のすべてのファイルとディレクトリを削除fs.rmdir(path, recursive=True, **kwargs) : path のディレクトリを削除 (再帰的に削除は、recursive=True を指定。 os.rmdir か os.rmtree で削除している)fs.rmfiles(paths, **kwargs) : リストで渡されたファイルを削除fs.rmdirs(paths, **kwargs) : リストで渡されたディレクトリを削除fs.mkdir(path, recursive=True, **kwargs) : Unix コマンドの mkdir と同じ。 recursive=True で、mkdirsfs.touch(path) : Unix のタッチコマンドと同じ。fs.list(path='.') : os.listdir(path) の結果を isfile してファイルだけ残して、 iterable にしている。fs.listdirs(path='.') : os.listdir(path) の結果を isdir してディレクトリだけ残して iterable にしている。fs.find(pattern, path='.', exclude=None, recursive=True) : パターンに指定されたファイルを iterable に返す。 exclude で除外ディレクトリも指定できる。再帰的適応も可。 os.walk で走査して、fnmatch.filter でフィルタしている。fs.finddirs(pattern, path='.', exclude=None, recursive=True) : find のディレクトリ版。fs.join(*args, **kwargs) : os.path.join(*args, **kwargs) と同じ。 +リストで引数を渡すことができる。fs.extname(path, **kwargs) : name, ext = os.path.splitext(path, **kwargs) の ext を返す。fs.open(path, mode='r', **kwargs) : 標準の open(path, mode, **kwargs)fs.write(path, content, encoding="UTF-8", append=False, raw=False) : 標準の open を使って エンコード指定で書き込む。fs.read(path, encoding="UTF-8") : 標準の open を使って、エンコード指定で読み込む。fs.append(*args, **kwargs) : fs.write(*args, append=True, **kwargs)fs.get(*args, **kwargs) : fs.read(*args, **kwargs)fs.put(*args, **kwargs) : fs.write(*args, **kwargs)fs.filename(*args, **kwargs) : fs.basename(*args, **kwargs)fs.extension(*args, **kwargs) : fs.extname(*args, **kwargs)要するに、a pythonic file system wrapper for humansAn easy to use file system wrapper for Python that aims to simplify os, os.path, os.walk, shutils, fnmatch, etcということ。サンプルを少し見てみる。*.xls か、*.xlsx を探してきて何かしたい。for filename in fs.find(['*.xls', '*.xlsx']): passconfig ディレクトリにある *.ini ファイルを local_* 以外取り出して何かしたい。for filename in fs.find('*.ini', path='config', exclude='local_*'): passVagrantfile を config ディレクトリから探して何かしたい。見つからなければ None。filename = next( fs.find('Vagrantfile', path='config'), None)backup ディレクトリにある *.sql のうち最新のアクセス時刻があるファイルを取り出して何かしたい。filename = max( fs.find('*.sql', path='backup'), key=fs.ctime).git ディレクトリを見つけて削除したい。for dir in fs.finddirs('.git'): fs.truncate(dir)なくても困らないけど、あれば、便利で、書くコードが短くて済むし、可読性もよくなるので、ちょっとツールを作るときに重宝すると思う。
2015.04.12
コメント(0)
処理したいファイルを GUI で選んで、何かするというのは、よく使うと思うので書いておく。ファイルを選択するには、GetFile(directory='', filename='', multiple=False, wildcard='All Files (*.*)|*.*', title="Select file(s)")multiple=False だと、1つのファイルだけ選択でき、multiple=True だと複数ファイルを選択でき、リストが返される。ディレクトリを選択したいときは、GetDir(path="", title='Select a directory')保存したいときは、SetFile(directory='', filename='', overwrite=False, wildcard='All Files (*.*)|*.*', title="保存する"):例えば、こうやって、ファイルを選択する。1つの場合と、複数の場合を試す。加えて、*.py だけ対象にするとかフィルタをかけられるのでやってみる。# -*- coding: utf-8 -*-import quickgui as qfilename = q.getfile(directory='/etc', multiple=False, wildcard='All Files (*.*)|*.*', title="ファイルを選択してください")print(filename)filename = q.getfile(directory='.', multiple=True, wildcard='Python sources (*.py)|*.py', title="ファイルを選択してください")print(filename)/etc を指定して、開いたところ。カレントディレクトリを指定して開いたところ。/etc/ntp.conf[u'/home/kafka/work/quickgui/sample103.py']
2015.03.23
コメント(0)
以前、Python のファイル参照や操作は面倒だというあなたに path モジュール という記事を書いた。標準ライブラリの os.path はイマイチ使いにくい。Python を使ってディレクトリやファイルをたどりながら何かするのは面倒。たとえば、このディレクトリの下のファイル名が「~」で終わっているファイルを削除したいとかいうのを書こうとすると、unix だったら find コマンドを使って、find . -name \*~ -print -exec rm {} \; とかあるわけで、そんな風にもっと簡単にできないかなぁと思う人も多いだろう。で、path モジュールを使えば、この手のものも簡単に書けるようになる。path だと、import pathd = '/var/apache/htdocs'for f in d.walkfiles('*~'): f.removeのような書き方ができた。ちなみに、os.path (python 2) を見ると os.path.walk があるが os.path (python 3) にはない。os.walk が残っている。python 3 では、pathlib — オブジェクト指向のファイルシステムパス が追加されているが、やっぱりもっと直感的に使えるようなものが欲しい。そこで、pyfs の登場となる。"pip install pyfs" でインストール。import fstarget_path = /var/apache/htdocs# 一ファイルずつ削除for f in fs.find('*~', target_path): fs.rm(f)# あるいは、まとめて削除to_delete = fs.find('*~', target_path)fs.rmfiles( to_delete )path や pathlib のようにファイルパスをオブジェクトとして、それを使って操作するという感じではなく、直接的に UNIX のコマンドのような感じで操作できる。ということで、気に入ってしまった。ソースを見てみればわかるが、かなりの部分が os.path や os をラップしているだけなので、基本を覚えるのは簡単。fs.exists(path) : os.path.exists(path)fs.isfile(path) : os.path.isfile(path)fs.rename(oldPath, NewPath, **kwargs) : os.rename(oldPath, newPath, **kwargs)fs.chdir(path, **kwargs) : os.chdir(path, **kwargs)fs.stat(path) : os.stat(path)fs.ctime(path) : os.stat(path).st_ctimefs.atime(path) : os.stat(path).st_atimefs.mtime(path) : os.stat(path).st_mtimefs.abspath(path, **kwargs) : os.path.abspath(path, **kwargs)fs.normalize(path, **kwargs) : os.path.normpath(path, **kwargs)fs.rm(path, **kwargs) : os.unlink(path, **kwargs)fs.unlink(*args, **kwargs) : os.unlink(path, **kwargs)fs.rmdir(path, recursive=True, **kwargs) : shutil.rmtree(path, **kwargs)fs.rmfiles(paths, **kwargs) : os.unlink(path, **kwargs)fs.exists(path, **kwargs) : os.path.exists(path, **kwargs)fs.cwd() : os.getcwd()fs.basename(path, ext="") : os.path.basename(path).replace(ext, "")fs.dirname(path) : os.path.dirname(path)fs.sep : os.path.sepこれらに加えて、fs.truncate(path, **kwargs) : path 以下のすべてのファイルとディレクトリを削除fs.rmdir(path, recursive=True, **kwargs) : path のディレクトリを削除 (再帰的に削除は、recursive=True を指定。 os.rmdir か os.rmtree で削除している)fs.rmfiles(paths, **kwargs) : リストで渡されたファイルを削除fs.rmdirs(paths, **kwargs) : リストで渡されたディレクトリを削除fs.mkdir(path, recursive=True, **kwargs) : Unix コマンドの mkdir と同じ。 recursive=True で、mkdirsfs.touch(path) : Unix のタッチコマンドと同じ。fs.list(path='.') : os.listdir(path) の結果を isfile して ファイルだけ残して、iterable にしている。fs.listdirs(path='.') : os.listdir(path) の結果を isdir して ディレクトリだけ残してiterable にしている。fs.find(pattern, path='.', exclude=None, recursive=True) : パターンに指定されたファイルを iterable に返す。 exclude で除外ディレクトリも指定できる。再帰的適応も可。 os.walk で走査して、fnmatch.filter でフィルタしている。fs.finddirs(pattern, path='.', exclude=None, recursive=True) : find のディレクトリ版。fs.join(*args, **kwargs) : os.path.join(*args, **kwargs) と同じ。 +リストで引数を渡すことができる。fs.extname(path, **kwargs) : name, ext = os.path.splitext(path, **kwargs) の ext を返す。fs.open(path, mode='r', **kwargs) : 標準の open(path, mode, **kwargs)fs.write(path, content, encoding="UTF-8", append=False, raw=False) : 標準の open を使ってエンコード指定で書き込む。fs.read(path, encoding="UTF-8") : 標準の open を使って、エンコード指定で読み込む。fs.append(*args, **kwargs) : fs.write(*args, append=True, **kwargs)fs.get(*args, **kwargs) : fs.read(*args, **kwargs)fs.put(*args, **kwargs) : fs.write(*args, **kwargs)fs.filename(*args, **kwargs) : fs.basename(*args, **kwargs)fs.extension(*args, **kwargs) : fs.extname(*args, **kwargs)要するに、a pythonic file system wrapper for humansAn easy to use file system wrapper for Python that aims to simplify os, os.path, os.walk, shutils, fnmatch, etcということ。サンプルを少し見てみる。*.xls か、*.xlsx を探してきて何かしたい。for filename in fs.find(['*.xls', '*.xlsx']): passconfig ディレクトリにある *.ini ファイルを local_* 以外取り出して何かしたい。for filename in fs.find('*.ini', path='config', exclude='local_*'): passVagrantfile を config ディレクトリから探して何かしたい。見つからなければ None。filename = next( fs.find('Vagrantfile', path='config'), None)backup ディレクトリにある *.sql のうち最新のアクセス時刻があるファイルを取り出して何かしたい。filename = max( fs.find('*.sql', path='backup'), key=fs.ctime).git ディレクトリを見つけて削除したい。for dir in fs.finddirs('.git'): fs.truncate(dir)なくても困らないけど、あれば、便利で、書くコードが短くて済むし、可読性もよくなるので、ちょっとツールを作るときに重宝すると思う。
2015.03.23
コメント(0)
最近書いた記事をちょっと振り返ってみる。最近書いた quickgui 関連の記事quickgui 意外と便利quickgui を改造してみる (1) - シンプルな msgbox を追加quickgui を改造してみる (2) - 間延びした Inputs をコンパクトにしてみるquickgui を改造してみる (3) - やっぱりプログレスバーが欲しいquickgui を改造してみる (4) - リストを表示したいquickgui を改造してみる (5) - リスト表示から選択するquickgui を改造してみる (6) - リスト表示を改良するquickgui を改造してみる (7) - リスト表示を改良する以前書いた wxpython 関連の記事かなり前 (2010年に書いた記事) に wxPython 入門を書いたので、まとめておく。動画で学ぶ wxPython を使った GUI プログラミングwxPython を断片から学んでみるwxPython 入門 (1) フレームとアプリケーションwxPython 入門 (2) テキストコントロールwxPython 入門 (3) 文字色、背景色とフォントwxPython 入門 (4) メニューとステータスバーwxPython 入門 (5) イベントとバインドwxPython 入門 (6) (5) のソースコードwxPython 入門 (7) プログラムの終了とダイアログの表示wxPython 入門 (8) ファイルを開くダイアログwxPython 入門 (9) (8) のソースコードwxPython 入門 (10) ウィンドウ配置の概要wxPython 入門 (11) Sizer を使ったレイアウトを配置wxPython 入門 (12) Sizer を使ったレイアウトを配置 2 と パネルにラベルを付けてみる当サイトでよく読まれている記事ちなみに、当サイトで今よく読まれているページは、次のものらしい。RaspberryPi 関連の記事が上位にあるようだ。Raspberry Pi にシャットダウンボタンをつける閲覧数 1225 | 2014年12月22日Raspberry Pi に赤外線モーションセンサーをつないでみた閲覧数 905 | 2014年12月21日Raspberry Pi と Sony RC-S380/P、nfcpy で NFC カードの IDm を読み取る閲覧数 2450 | 2014年02月24日Raspberry Pi 2 買おうかなぁw【Raspberry Pi 2 ModelB】2015年2月1日発売最近機種!RaspberryPi2(ラズベリーパイ2)モデルB 英国製【Raspberry Pi 2 ModelB】2015年2月1日発売最近機種!RaspberryPi2(ラズベリーパイ2)モデルB 英国製 【売れ筋】【オススメ】
2015.03.08
コメント(0)
quickgui を改造してみる (6) - リスト表示を改良するで、quickgui に追加したコードは、次のようなもの。wxPython: Adding Checkboxes to ObjectListViewを参考にさせていただいた。from ObjectListView import ObjectListView, ColumnDefn class OLVCheckPanel(wx.Panel): """""" def __init__(self, parent, columns, data, func, func_arg): """Constructor""" wx.Panel.__init__(self, parent=parent) self.func = func self.func_arg = func_arg mainSizer = wx.BoxSizer(wx.VERTICAL) btnSizer = wx.BoxSizer(wx.HORIZONTAL) self.resultsOlv = ObjectListView(self, style=wx.LC_REPORT|wx.SUNKEN_BORDER) self.data = data self.setResults(columns, data) checkBtn = wx.Button(self, label="Check") checkBtn.Bind(wx.EVT_BUTTON, self.onCheck) btnSizer.Add(checkBtn, 0, wx.ALL, 5) uncheckBtn = wx.Button(self, label="Uncheck") uncheckBtn.Bind(wx.EVT_BUTTON, self.onUncheck) btnSizer.Add(uncheckBtn, 0, wx.ALL, 5) nextBtn = wx.Button(self, label="Next") nextBtn.Bind(wx.EVT_BUTTON, self.onNext) btnSizer.Add(nextBtn, 0, wx.ALL, 5) mainSizer.Add(self.resultsOlv, 1, wx.EXPAND|wx.ALL, 5) mainSizer.Add(btnSizer, 0, wx.CENTER|wx.ALL, 5) self.SetSizer(mainSizer) def onCheck(self, event): """""" objects = self.resultsOlv.GetObjects() for obj in objects: self.resultsOlv.SetCheckState(obj, True) self.resultsOlv.RefreshObjects(objects) def onUncheck(self, event): """""" objects = self.resultsOlv.GetObjects() for obj in objects: self.resultsOlv.SetCheckState(obj, False) self.resultsOlv.RefreshObjects(objects) def onNext(self, event): """""" obj = self.resultsOlv.GetObjects() status = [] for o in obj: s = self.resultsOlv.GetCheckState(o) status.append(s) self.func(status, self.func_arg[0], self.func_arg[1]) self.Destroy() wx.Exit() def setResults(self, columns, data): """""" self.resultsOlv.SetColumns(columns) self.resultsOlv.CreateCheckStateColumn() self.resultsOlv.SetObjects(self.data)class OLVCheckFrame(wx.Frame): def __init__(self, title, columns, data, func, size=(500,200)): """Constructor""" wx.Frame.__init__(self, parent=None, title=title, size=size) func_arg = (columns, data) make_objects = self.column_builder(columns) column_definition = self.column_def(columns) data = [make_objects(x) for x in data] self.panel = OLVCheckPanel(self, column_definition, data, func, func_arg) def column_def(self, name): columns = [] for i, n in enumerate(name): slot = "column_%d" % i column = ColumnDefn(n, "left", -3, slot) columns.append(column) return columns def column_builder(self, columns): l = len(columns) slots = [] for i in range(l): column = "column_%d" % i slots.append(column) class Results(object): __slots__ = slots def __init__(self, data): """Constructor""" for i in range(len(slots)): self.__setattr__(self.__slots__[i], data[i]) return Resultsdef CheckList(title, columns, data, func, size): app = wx.App(False) frame = OLVCheckFrame(title, columns, data, func, size=size) frame.Show() app.MainLoop() return Truechecklist = CheckList
2015.03.08
コメント(0)
quickgui を改造してみる (5) - リスト表示から選択するは、ちょっと見た目もさえないし、タイトルをクリックしたら並び替えてくれるとか、機能的にも、もう少し欲しい。ということで、wxPython: Adding Checkboxes to ObjectListView を参考にする。ObjectListView を使っているので pip install しておく。# -*- coding: utf-8 -*-import quickgui as q # 改造したものtitle = "デタラメデータ"columns = ("名前", "出生地", "生年", "血液型", "好きな食べ物")data = [("平 将門", "東京都", "1981", "A", "チョコレート"), ("平 清盛", "神奈川県", "1949", "B", "メロン"), ("宮本 武蔵", "埼玉県", "1949", "AB", "いちじく") ] def func(check_list, columns, data): print "チェックされたもの" for c in columns: print c, print count = 0 for checked in check_list: if checked: column_data = data[count] for d in column_data: print d, print count += 1q.checklist(title, columns, data, func, size=(500,200))これだけで、次のような表示になる。Nextボタンを押すと、func が実行され、上の場合、標準出力に結果を出力するようにしている。チェックされたもの名前 出生地 生年 血液型 好きな食べ物平 将門 東京都 1981 A チョコレート宮本 武蔵 埼玉県 1949 AB いちじくタイトル行をクリックすると、ソートしてくれるし、色もついて、複数行あるときに見やすくなった。ObjectListView - How I learned to stop worrying and love wx.ListCtrl をちゃんと読んで、ちゃんと使い方覚えようかな。追加したコードは、次のエントリで。
2015.03.08
コメント(0)
ここまで来たら、リストで表示されているものを選んで OK したら、選択されているものの結果を返すというのができないかとチャレンジしてみる。quickgui に次のコードを追加。import sysfrom wx.lib.mixins.listctrl import ListCtrlAutoWidthMixinclass AutoWidthListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin): def __init__(self, parent): wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT) ListCtrlAutoWidthMixin.__init__(self)class AutoList(wx.Frame): def __init__(self, parent, id, title, columns, data, size=(400, 200)): wx.Frame.__init__(self, parent, id, title, size=size) hbox = wx.BoxSizer(wx.HORIZONTAL) panel = wx.Panel(self, -1) self.list = AutoWidthListCtrl(panel) for i, name in enumerate(columns): self.list.InsertColumn(i, name) number_of_data = i for i in data: index = self.list.InsertStringItem(sys.maxint, i[0]) rest = len(i) - 1 for j in range(rest): self.list.SetStringItem(index, j+1, i[j+1]) hbox.Add(self.list, 1, wx.EXPAND) panel.SetSizer(hbox) self.Centre() self.Show(True)def autolist(title, columns, data): app = wx.App() AutoList(None, -1, title, columns, data) app.MainLoop()そして、使うときは次のようにする。# -*- coding:utf-8 -*-import quickgui as qcolumns =('名前','出生地','生年','血液型','好きな食べ物')data = [('平 将門', '東京都', '1981', 'A','チョコレート'), ('平 清盛', '神奈川県', '1949','B','メロン'), ('宮本 武蔵', '埼玉県', '1949','AB','いちじく'),]q.autolist("デタラメデータ", columns, data, size=(200,100))こんな感じになる。簡単にチェックボックス付きのリストが表示できるようになった。なんか地味だし、もうちょっとよくしたいので、なんとかしてみる。
2015.03.01
コメント(0)
ここまできたらもっとやってみるだ。何か検索結果を簡単に一覧表示したいときがある。じゃあ、やってみる。参考にしたのは、String formating in wx.ListBoxあたりだったかな。しばらく前に書いたものなので忘れてしまった。タイトル、カラム名のリスト、データのリストを渡してやると、一覧表示してくれるようなものを作ってみた。まずは、quickgui に以下を追加しておく。import sysfrom wx.lib.mixins.listctrl import ListCtrlAutoWidthMixinclass AutoWidthListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin): def __init__(self, parent): wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT) ListCtrlAutoWidthMixin.__init__(self)class AutoList(wx.Frame): def __init__(self, parent, id, title, columns, data, size=(400, 200)): wx.Frame.__init__(self, parent, id, title, size=size) hbox = wx.BoxSizer(wx.HORIZONTAL) panel = wx.Panel(self, -1) self.list = AutoWidthListCtrl(panel) for i, name in enumerate(columns): self.list.InsertColumn(i, name) number_of_data = i for i in data: index = self.list.InsertStringItem(sys.maxint, i[0]) rest = len(i) - 1 for j in range(rest): self.list.SetStringItem(index, j+1, i[j+1]) hbox.Add(self.list, 1, wx.EXPAND) panel.SetSizer(hbox) self.Centre() self.Show(True)def autolist(title, columns, data): app = wx.App() AutoList(None, -1, title, columns, data) app.MainLoop()呼び出してみる。呼び出しは簡単。サイズもオプションで指定できるようにしてみた。# -*- coding:utf-8 -*-import quickgui as qcolumns =('名前','出生地','生年','血液型','好きな食べ物')data = [('平 将門', '東京都', '1981', 'A','チョコレート'), ('平 清盛', '神奈川県', '1949','B','メロン'), ('宮本 武蔵', '埼玉県', '1949','AB','いちじく'),]q.autolist("デタラメデータ", columns, data, size=(200,100))なかなか便利かもしれない。
2015.02.26
コメント(0)
quickgui を自分好みに改造したついでなので、プログレスバーも簡単に使えればいいかと思って追加してみた。Updating a wxPython progress bar after calling app.MainLoop() を参考にして、次のコードを quickgui に追加。def guage(title, func, msg = "processing..."): import threading def start(func, *args): # helper method to run a function in another thread thread = threading.Thread(target=func, args=args) thread.setDaemon(True) thread.start() app = wx.PySimpleApp() dialog = wx.ProgressDialog(title, msg) start(func, dialog) dialog.ShowModal() app.MainLoop() return True使うときには、引数として渡してやる関数に更新のロジックを書けばいい。wx.CallAfter の行を入れればいいだけなので、毎回長いコードを書くよりはるかに楽かなと。# -*- coding: utf-8 -*-import wximport quickgui # 改造中のものimport timedef do_something(dialog): max_size = 400 # 400回のループを回してみる step = 100.0 / max_size count = 0.0 for i in range(max_size): count += step wx.CallAfter(dialog.Update, count) time.sleep(0.1) # 実際の処理をここに wx.CallAfter(dialog.Destroy) quickgui.guage("メッセージ処理", do_something, msg="処理中です...")
2015.02.19
コメント(0)
quickgui の Inputs に手を入れて、_Inputs2、Inputs2 というバリエーションを作ってみた。ヘルプボタンを削除したら、表示時のスペースが少なくなって、コンパクトになるかなと。これはソースが長いので省略。単純にいえば、helpボタン関連の行をコメントアウトして、instruction で渡された文字列は先頭に表示するという改造。、子供でもできる Python をこんな風にしてみた。# -*- coding: utf-8 -*-import quickgui # 改造バージョンintro_message = "実行したいツールをダブルクリックしてください。"choices = [ (''), (u' ツールの選択', (u"いかがわしいツール", u"なぜかいかがわしいツール", u"とってもいかがわしいツール", u"もっといかがわしいツール", u"さらにいかがわしいツール", u"どうしようもなくいかがわしいツール"), 0), (''), ]choice = quickgui.inputs2(choices, title="ツール選択", instruction=intro_message)print choicereply = choice[0]if reply[0] == u"いかがわしいツール": quickgui.confirm(u"%s を実行します。" % reply[0], ok=True) # なにやらいかがわしいことをする。else: quickgui.alert(u"%s はまだ実装されていません。" % reply[0])quickgui.message("終わり")元々の表示Inputs2 改良版ここでふと、FlexGridSizer の使い方変えれば、元のままでもいいかなと思い始める。つまり、FlexGridSizer で2列用意して、ヘルプボタンと、キャンセルボタンの2つが、最初の列になるので、最初の列が長くなってしまう。だから、入力用の FlexGridSizer には入れないで、別に作ったところに入れてやればいいかと。それで、こうなった。これでいいかも。と、まあ、少し wxPython をいじったことがあれば適当に手を加えて自分好みに改造できる。せっかくだから、もう少し改造というか拡張を続けてみようかと思う。
2015.02.17
コメント(0)
quickgui は便利なのだけれど、ちょっと好みに合わないところがあるので、手を入れてみることにした。最初に、シンプルな msgbox を作って、ソースに追加してみた。これで easygui みたいなメッセージボックスを表示できるようになった。class _SimpleMessageDialog(wx.Dialog): def __init__(self, message, title, ok_button): wx.Dialog.__init__(self, None, -1, title,size=(400, 80)) self.CenterOnScreen(wx.BOTH) button = wx.Button(self, label=ok_button) stMsg = wx.StaticText(self, -1, message) vbox = wx.BoxSizer(wx.VERTICAL) vbox.Add(stMsg, 1, wx.ALIGN_CENTER|wx.TOP, 10) vbox.Add(button,1, wx.ALIGN_CENTER|wx.TOP, 10) self.SetSizer(vbox) self.Bind(wx.EVT_BUTTON, self.OnExit, id=button.GetId()) def OnExit(self, event): self.Close()def MessageBox(msg, title='Message', ok_button="OK"): """Messagebox(msg, title='Message', ok_button="OK") Displays simple message box """ dlg = _SimpleMessageDialog(msg, title, ok_button) result = dlg.ShowModal() return resultmsgbox = MessageBox
2015.02.11
コメント(0)
Python のプログラムを作ったとき、コマンドラインで動くようなものを作ったけれど、オプションを GUI で指定したり、メッセージもちょこっと GUI で出したりとかしたいとき、easygui とか使うと便利。でも、Tk ベースなのでなんか見栄えが微妙。wxPython とか、pyQt とか、ごりっと使って、まともに GUI プログラミングをするのには億劫う。なんてときは、quickgui を使う。easygui は以前に 子供でもできる Python (2007年10月16日)でも紹介したが、quickgui は wxPython 版ということ。quickgui のベースは wxPython なのだけど、インタラクティブな操作のところを簡単に書ける。バックエンドに何を使っているかというところから見ると、次のようになる。easygui: Tkinterquickgui: wxPythoneasygui-qt, (doc) PyQtwxPython ベースの quickgui を使うことにした。pyQT 使える人なら easygui-qt とかの方がいいかもしれない。使ってみた感想として、easygui と比べると、easygui の方がイージー。msgbox, ccbox, ynbox, choicebox とか、名前が安易でわかりやすい。quickgui だと、メッセージを出す場合には alert、confirm、message とわかりやすい名前で使い分けられる一方で、入力は Inputs への引数の渡し方で、radiobox になったり、combobox になったり、あるいは listbox、checkbox, textbox になる。名前をあれこれ覚えなくてもよい一方、引数の渡し方でタイプが決まるので、3つの要素がある radiobox とか表示できなかったりする(3つの要素のリストを渡すと自動的に comboboxになってしまう)。微妙な不自由さはあるものの、逆に一つのダイアログの中に複数のタイプの入力を並べることもできる。制限はあるが、簡単にできることだけ簡単にやるということなので、よしとしよう。ちなみに messageでメッセージを表示すると、カウントダウンして、10秒(変更可能)で OK を押したのと同じになる。便利なときは便利だけど、カウントダウンが邪魔だなと思う時もある。confirm("メッセージ", ok=True) で easygui.msgbox と同じ感じになる。でも、アイコン邪魔とかいうときはどうするの? アイコンは勝手に表示されちゃう。便利は便利なんだけど、微妙。あと、子供でもできる Pythonで作ったやつを同じ感じでやろうとしても、こうなっちゃう。微妙な配置。easyguiquickguiちょっと quickgui に手を入れながら、もう少し便利に使えるようにあれチャレンジしてみることにした。
2015.02.09
コメント(0)
ajenti (GitHub Eugeny/ajenti)を試してみた。主として Python で書かれたサーバー管理ツールで、arnes (The Academic and Research Network of Slovenia によって開発され公開されているもの。今風の作りで感じいい。スロベニアのソフト使うの初めてだ。GitHub みたいな公開レポジトリってほんとうに世界を身近にしてくれる。How To: Manage your servers with the Ajenti admin panel、Install Ajenti (A Web Based Control Panel) for Managing Linux Server、Ajenti (Wikipedia) も参照。Ajenti documentation も参照。これを見るとだいたいの感じが分かる(14:29)。ajenti は Pleask や cPanel、Webmin などに相当するもので、軽量で VPS などで使えるように開発されたようだ。個人利用(自分のサーバ、自社内での利用、教育機関を含む)の場合は自由に使えるようだ。VPS やホスティング会社など第三者にサービスを提供するときには有料のライセンスが用意されている。仮想ホスト用の ajenti-v もある。インストールは、ダウンロードからプラットフォームに合わせたスクリプト・パッケージが用意されている ので簡単。Debian, Ubuntu, RedHat, CentOS, FreeBSD 用が提供されている。とりあえず lxc の仮想環境にインストールしてみた。インストールしたら、https://myserver:8000/ でアクセスするとダッシュボードが表示される (デフォルトのユーザーとパスワードは、root/admin)。日本語対応もしていて素晴らしい。プラグインから、Apache、APC UPS Staus、BIND9 等々のパッケージのインストールが簡単にできるようになっている。またファイアウォールの設定もできるし、サービスの状態確認、起動や終了、プロセスの確認。SNMPの設定などもできる。Terminal もウェブ経由で使える。一通りのことは問題なくできてしまう。パッケージのインストールは、Packages からできる。例えば、Munin をインストールすれば、SOFTWARE - Munin からグラフの参照も可能。ウィジェット化してダッシュボードに貼り付けることもできそうだが、なんかバグってるっぽい。新しいバージョンになったら直りそう。とにかく、さくっとインストールできて、簡単に使えるのでよい感じ。よくできてる。ただし、このソフトのセキュリティを破られたらなんでもできるに等しいので、パスワード認証以外にもアクセス制限をしておかないと怖いかも。
2014.08.24
コメント(0)
pyvideo.org には、2082 個の Python 関連のビデオがある。と思ったら、About this siteを見ると、実はビデオそのものはなくてインデックスなのね。実際のビデオは、いろいろなサイトにあって、メタ情報が置かれていて参照できるようになっているということか。サイトのソースコードは、http://github.com/willkg/richard、メタデータ関連のソースコードは、http://github.com/willkg/steve に公開されている。カンファレンス関連のビデオが集められているので、暇を見つけて見てみようかな。
2014.04.14
コメント(0)
matplotlib でデフォルト表示したら、こんな風になったとする。これじゃあ、よくわからないよ。。。。もっと簡単きれいに出力できないんだろうか。デフォルトでも次のようにきれいに出力できたらうれしいのに。prettyplotlib は、Edward Tufteさんのインフォメーションデザインについての成果や、Cynthia Brewerさんの color perception の成果に触発されて、Olga Botvinnik さんが githb 上で公開しているもの。このライブラリそのものとは別の話だが、Olga Botvinnikさん、女性なのね。 RNA, data visualization, and computational reproducibility の研究している方。Cynthia A. Brewerさんは Professor of Geography。インターネットが普及して、地道にあれこれやって公開している人が一般の人の目に触れるようになってる。この数年、女性の活躍が一段と目立ってきた印象がある。YouTube 見てても、それなりに動画あるしね。もっとも現状では、女性でもこういう活躍している人がいるのねと思ってしまう程度にメジャーではないというのもあるけれど。話は元に戻って、Olga Botvinnik さんの貢献しているプロジェクトを見てみると、Seaborn: statistical data visualization、python-pds: Toy Implementation of Probabilistic Data Structures in Python、matplotlib、pandas: Flexible and powerful data analysis / manipulation library for Python, providing labeled data structures similar to R data.frame objects, statistical functions と、バリバリ Python 使っている感じ。R でなくて、pandas 使ってるし。Python で全部やってしまうというのが、どんどん進んでるのね。R は R で進化しているみたいだけど。prettuplotlib を使うには、numpy、matplotlib、brewer2mpl などをインストールしておく必要がある。安易に現状の Google の検索結果から Matplotlib と Pandas のリンクをメモ。時間をおいて検索してみると、どの程度普及が進んだか分かるかなと。Matplotlibpython環境 に matplotlib を入れるPython, SciPy, matplotlibのインストール(Windows)Matplotlib 利用ノートmatplotlib 入門Scipy lecture notes » 1. 科学技術計算のために Python を始めよう。 » 1.4. Matplotlib: 作図matplotlib を使ってグラフを簡単表示Matplotlib サンプル集フーリエ変換入門(FFT入門)> Pythonでグラフ描画:matplotlib(6)■[python][matplotlib]matplotlibのグラフの体裁を整える[python][matplotlib]matplotlibでグラフを書くAdd Star毎度のグラフ描画スクリプトAdd Starpgplot で可能なことはmatplotlib でできそうだ。PythonでGeoSpatial Dataの読み書きについて_3[Chapter 10]【Matplotlib】温度とFAN回転率解析「ipmiSensor9.py」リリースPandasPythonデータ解析ライブラリpandasと遊ぶ:クロス集計~検定・残差分析までデータ分析がデキるITエンジニアになるために必要な「道具」を揃える (3/4)データ分析ライブラリPandasの使い方pandasメモ【Python】時系列データをスプライン曲線でイイカンジに補完する【pandas】kaggleにpythonを使ってみる(1) 〜pandaspython - pandas のデータいじり・・・メモ1書籍Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理【送料無料】Pythonによるデータ分析入門 [ ウェス・マッキニー ]
2014.01.12
コメント(0)
querycsv.py を使うと、次のように SQLデータベースと同じ形式でクエリが実行できる。-i でデータファイルを指定する。querycsv.py -i testdata.csv "select somecolumn from testdata;"地味に便利かもしれない。ということで、いじってみた。querycsv.py -i testdata.csv "select max(somecolumn) from testdata;"みたいなこともできる。sum(somecolumn)とかもできる。どこまで対応しているか? SQLite にできることはできる。なぜならば、sqlite3.connect(":memory:") で開いた SQLite にデータを CSVファイルから読み込んでから、それに対してクエリを実行しているから。なんだそういうことかぁ。-f オプションを指定するとオンメモリではなく、SQLite ファイルを使う。ちなみに、insert とか update とかしても元の CSV ファイルには影響がない。オンメモリでなく SQLite のデータベースファイルに書き出すこともできる。-f オプションで SQLite のデータベースファイルを指定し、適当なクエリを書く。-k オプションをつけるのを忘れないように。keep の意味で、実行後に SQLite ファイルを残すということ。-k がないと、SQLite ファイルが残らない。querycsv.py -i testdata.csv -f testdata.sqlite -k "select * from testdata;"生成された SQLite 形式のデータベースを入力として使うこともできる。同じデータに対して操作をするなら、その方が早いしね。-u で use するファイルを指定。querycsv.py -u testdata.sqlite "select distinct somecolumn from testdata;"実行する SQL文はファイルにしておいて、-s オプションで指定することもできる。複数のデータベースファイルを JOIN するとかできる。問題としては、このままだと日本語のデータが入っているとエラーになる。UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-4: ordinal not in range(128)まあ、そうだろうなとちょこちょこと手を入れたら、日本語も扱えるようになった。便利かもしれない。どのあたりに手を入れたかと言えば、前に紹介した unicodecsv を使ってcsv データの読み書きをする。読み込んだ文字列はユニコードになるから、ascii の文字列とユニコードの文字列を + で連結しようとするとエラーになるので、そのあたり手を入れてみた。表示のときの文字幅が日本語だとちょっとやっかいなので、次のような関数を作って文字幅とした。全角文字か不明の場合は、2文字分の幅、それ以外なら 1 文字分の幅とする。u'あア a' なら 6 が返る。でも、端末で表示すると、そういう単純なやり方だときれいにそろわなかったりするけど...。経験的にスペース量を調整するようなコードを書いてみたが、スペースを入れない方が、むしろ見やすくて、潔い態度かもしれないなぁとか呟きながらも、ゴニョゴニョ...。# 文字幅のカウントimport unicodedatadef uwidth(ustr): l = 0 for uc in ustr: l += 2 if unicodedata.east_asian_width(uc) in ('F','W','A') else 1 return lあと、querycsv.py のソースを見ていて、csv.Sniffer という存在に今更ながら気づいた。クォートがついているついてないとか、デリミターはなんだとか、形式を推定してくれるのね。って、前にも思ったことがある...。すぐ忘れる。csvfile = open("example.csv", "rb")dialect = csv.Sniffer().sniff(csvfile.read(1024))csvfile.seek(0)reader = csv.reader(csvfile, dialect)...参照 13.1. csv — CSV File Reading and Writingquerycsv だと、open するとき "rt" になっているけれど、"rb" の方がよさそうか。unicodecsv では、sniffer がないので、判定は csv.Sniffer を使って、読み込むところだけやらせた。とか、久々にコードをいじくっているうちに、大晦日があけて元旦を迎えてしまった。そういえば、まだ、私 Python 2 使ってんのねwとりあえず、こんな風になった。備考の後ろの「|」が揃ってるのね。単純に全角だから2文字分とかカウントしているだけではだめ。ljust でスペースを入れているところも直さないといけなかった。ということで、なんだか中途半端でいい加減な終わり方だけど、本年もよろしくお願いいたします。
2014.01.01
コメント(0)
PC上にヌード写真などが保存されていないかどうかをチェックするためのスクリプトを書いてみた。判定は、nudepy 0.1.2を使った。import sysimport osimport globimport nudefrom nude import Nudewhere_to_search = sys.argv[1]for root, dirs, files in os.walk(where_to_search): for filename in glob.glob(os.path.join(root,'*.jpg')): try: result = nude.is_nude(filename) if result: print filename except: passpython nude_hunter.py ~/ のように、引数に開始ディレクトリを指定して動かすと、jpg ファイルを探しだして、ヌード画像かどうかを判定し、ヌード写真と判定されると、ファイル名を出力する。で、精度はどうなのかというと、誤ってこういうファイルもヌードと判定されてしまうとかいうこともあるが(確かにいやらしい画像だ...)、ヌードは比較的よく拾ってくれる感じで、それなりに実用性はあるんじゃないかと思う。で、アルゴリズム的にどうやっているのかなというと nude.js を Python にポートしたもののようなので、そっちを見てみると、https://sites.google.com/a/dcs.upd.edu.ph/csp-proceedings/Home/pcsc-2005/AI4.pdf?attredirects=0 をベースにしているとのこと。速度は速いとは言えないので、pypy とか使って、ぱいぱいヌードハンターという表題にすることも考えたが、試していない。
2013.06.09
コメント(0)
pdf-link-checker を使うと、PDFファイル内のリンクをたどって、リンク切れの URL があれば、エラーを出してくれる。リンク入りの PDF を作るときには、これでチェックを入れるとよいかも。$ sudo pip install pdf-link-checker$ pdf-link-checker sample.pdfERROR: URL http://sample.com/download failed. Reason: HTTP Error 404: Not FoundERROR: URL http://sample.com/ failed. Reason: timed out
2013.05.06
コメント(0)
Pythonの対話的環境 IPython (1) notebook が素敵の続き。ipython の現状をつかむためにビデオを見てみる。IPython: Python at your fingertips最初に "The IPython notebook" を見ると、5分半ほどで notebook の基本的な使い方がわかる。これをもう少し説明的に見るなら、"The IPython Notebook for Data Science"単に python を実行するだけでなくて、その名の通り、ちゃんとノートブックになるのだな。例えば、matplotlib - 2D and 3D plotting in Python みたいなページが作れてしまう。メモを残しながら試行錯誤で計算できる環境だから、自分のために使えるし、A gallery of interesting IPython Notebooksのように公開用にも適している。もうちょっと詳しく見るなら IPython: Python at your fingertips。40分弱。
2013.03.03
コメント(0)
Python をインタラクティブに使う環境として、IPython がある。Python が使えるシェル環境(shell) の一つ。これがとっても強力。以前 IPython 0.8.2 で一段と便利になってる (2007.12.17)のころよりも進化していて、ウェブベースの notebook (An HTML Notebook IPython) を使えば、グラフも対話的に描画できてしまう。サイエンティスト系な人の間で利用者が増えているのだろうなという感じ。(IPython ipy_0.13.pngより)ブラウザからインタラクティブにグラフが描けるのは、便利。IPythonのページを見ると、matplotlibの作者で、IPythonへの貢献者であった John Hunter (1968-2012) 氏が 2012年 8月 2日に闘病の末亡くなったことを知る。ご冥福をお祈りする。残された子供たちの養育を支えるために John Hunter Memorial Fund が作られたようだ。という話はさておき、ipython で notebook を使うには、ipython notebookで起動する。matplotlib を使いたければ、ipython notebook --pylabさらに表示をブラウザ上でインライン表示したければ、ipython notebook --pylab inline日本語のページをいくつか。IPython0.12の新機能notebookを動かしてみたIPython notebook + youtube はとても良い勉強環境かもしれない というメモ もうすぐIPython Notebookが流行る気がするのでAdd Star
2013.02.24
コメント(0)
いつの間にか100万アクセスを突破していた。民主党政権が終わるか、100万アクセスを突破したら、また再開しようかなと思っていたので、また、頻繁に書こうかなということで、リハビリから始めることにした。とりあえず、どうでもいいことを書きながら、書く習慣を取り戻すってところからで。unicodecsv 0.9.4を見てみる。Python2's stdlib csv module is nice, but it doesn't support unicode. This module is a drop-in replacement which *does*.おい、おい、まだ Python2 なのかって、このところ、Python でプログラム書かなかったから、Python 2 でストップしたままなのであった。というのはさておき、本題の unicodecsv。python2 の csv モジュールは、UTF-8 を使う分には、問題ないのだけれど、Unicode だとエラーになる。#!/usr/bin/env python# -*- coding: utf-8 -*-import csvfrom cStringIO import StringIOf = StringIO()w = csv.writer(f)w.writerow(('日本語', 'どうでしょう'))f.seek(0)r = csv.reader(f)row = r.next()print row[0], row[1]w.writerow(('日本語', 'どうでしょう')) の行をw.writerow((u'日本語', u'どうでしょう')) だとエラーになる。まぁ、あたりまえの話だけれど。UTF-8 ではなく、ユニコードを直接扱いたいというのであれば、unicodecsv を使えばよい。pip install unicodecsv でインストールしておいて、#!/usr/bin/env python# -*- coding: utf-8 -*-import unicodecsvfrom cStringIO import StringIOf = StringIO()w = unicodecsv.writer(f, encoding='utf-8')w.writerow((u'日本語', u'どうでしょう'))f.seek(0)r = unicodecsv.reader(f, encoding='utf-8')row = r.next()print row[0], row[1]いや、標準の csv モジュールだって、Unicode の CSV データ (Unicode 文字列のリスト)を扱うための csv.reader をラップするジェネレータ(generator)をunicode_csv_reader() のように書いてやればちゃんと扱えるでしょって、いちいちそういうコードを入れなくてよいから楽にユニコードのcsvデータを扱えるよって話なのでした。
2013.01.29
コメント(0)
しばらく前に Web ブラウザで Python を実行する学習環境 で、ちらと PythonAnywhere に触れたが、ちょっとだけ実際に使ってみた。PythonAnywhere このサービスを使えば、ローカルに Python がインストールされていないマシンでもウェブブラウザがあれば Python プログラミングができてしまう(ブラウザ上に表示されたコンソールから vim や Emacs から編集することができる)。Effortless Python cloud computing ということなのね。登録すると 512Mb のフリーディスクスペースが使えるようになる。対応する Python のバージョンは、Python 2.6, 2.7, 3.2。コンソールは、iPython。コードの編集は、NumPy, SciPy, Mechanize, BeautifulSoup, pycrypto などもインストールされているので使うことができるし、ウェブベースのエディタが使える。ウェブアプリケーションも WSGI ベースで作ることができる。MySQL も使える。すごい。タスクの設定もできるので、自動実行とかもできる。スクレイピングを自動実行する環境とかにも使えるかも。ちなみにimport matplotlibimport matplotlib.pyplot as pltfig = plt.figure()ax = fig.add_subplot(111)ax.plot(range(100))fig.savefig('graph.png')を実行すると、http://www.pythonanywhere.com/user/kugutsushi/files/home/kugutsushi/graph.png こんな風にすることもできる。日本語はどうかと試したが、コンソールからは残念ながら日本語の入力ができなかった (.inputrc とか .bash_profile とか作ってもダメだった)。けれども、日本語を含むファイルを作って、アップロードして実行したら、ちゃんと日本語が表示された。Dropbox 対応しているので、ローカルでファイル編集して Dropbox で同期するのが楽かもしれない。何はともあれ、おもしろいサービスかもしれない。落ちとして、最近 Python でプログラム書いてないんだけど。。。。
2011.11.20
コメント(0)
以下のネタ元は、Ned Batchelder : Blog : Online Python exercises。上記記事によると Ned Batchelder さんは、オンラインの Python 学習サイトを考えているらしい。セットアップ不要で、サイトにアクセスすればコードを実際に書いて動かしながら学べるようなものを。ちょうど JavaScript の学習サイトだと Nathan's Javascript Lessons みたいなものを想定しているようだ。とりあえず、実際にやってみた。説明があって、演習問題というパターンでよい感じ。手を動かしながら確実に進んでいける。ブラウザで JavaScript を動かしてこういう仕組みを作るのは楽だけれど、Python だとどうよということで、あれこれ調べた結果が書かれている。まずはリサーチからってところだろうか。細かいところは、上記記事にあたってもらえばよいので、そこで挙げられているサイトだけ、ピックアップしておく。サーバーサイドで実際に学習者が入力したコードを制限付きで実行してしまうものから、サーバー上の sanbox で実行するもの (PyCon AU video by Tim Dawborn) から、同じサーバーで実行するにしても Jython を使ったものから、あれこれあるのね。サーバーサイドで実行すると、何らかのリスクが生じるから、ブラウザの中だけで動いてくれた方がよいよねということで、 IronPython + Silverlight とか、llvm-to-JavaScript コンパイラで CPython をブラウザ上で動かしちゃうすごいものから、Python を JavaScript で実装しちゃうものまであって、なんだかすごいなぁ。CodingBat - server sideNCSS Challenge - server side, sandbox Python Web Console - server side, Jython, GAE (detail)ScraperWiki Tutorials - server sideTry Python - IronPython + Silverlight (rst2xaml)Gumby - CPython, llvm-to-JavaScript (Javascript は 790Kb)Skulpt - Python in Javascriptそもそも Python を実際に利用するときには、Python をインストールして、環境整えなきゃってのがあるではないですか。であれば、あくまでブラウザ上でこだわるのって意味あるんだろうか。なんて、根源的な問いに戻っちゃったりしてw 実行するのは学習者の PC 上で、オンラインと自動的にうまくコミュニケーションできるような環境があったらよいのだろうか。等々、リサーチの結果を踏まえつつ、あれこれ考えていらっしゃるようだ。でも、逆にサーバー側から悪しきコードを送られてクライアント側で実行される危険性とかも考慮する必要があったりしないだろうかとか、思わないでもないけど。とか考え始めると面倒なことになりそうな。インストールの制限が厳しい学校とか組織とかの場合、やっぱり Webベースは有効だろうし、基本的なことを学ぶのであれば、やっぱり Webベースでどこからでも気軽にというのはメリットが大きいし。コメントのところを見ていたら、pythonanywhere なんていう環境もあるのだね。Effortless Python cloud computing というコンセプトで。いまのところ、無料で使える。ディスクスペースを増やす時に課金してとかいうモデルなのかな。 ちなみにサービスは、Amazon EC2を使っているようだ。で、サービス的には、Dropbox 上にソースコードをおいておくとか、git や ht, svn のようなバージョンコントコロールの環境からソースをダウンロードして実行するとかできるような環境になっているようだ。学習とは別に、環境としておもしろい。どこでも自分のPython環境が使えるってことね。ふと、Zope を思い出した。server side でやるなら RestrictedPythonみたいなやつもあるわなぁと思った。Sandboxed Python なども参照。そういえば、Python のコードを書くならば、PEP8 に準拠して書いた方がよいよね。pep8 - Python style guide checker なんてものがあって、pep8 optparse.py とかすると、ダメなところを指摘してくれたりするので、Pythonのコーディング規約pep8チェックをUnitTestに組み込んでみた とかしている方もいらっしゃる。でも、そもそも PEP8 読ん覚えてない。とりあえず、勝手に PEP8 準拠のソースに書き直してくれよっていうのであれば、autopep8 を使うと、autopep8 TARGET.py で勝手に、TARGET.py を PEP8 に準拠するように書き直してくれる。楽ちん。import sys, osとか不精なことをしても、import sysimport osとちゃんと書き直してくれる。その他、参考。Pep8 and pyflakes in emacsMaking pep8, pyflakes, etc work with virtualenv.flymakeライクなvimプラグインの続き(with pep8.py)emacs の python 開発環境を整える
2011.09.10
コメント(1)
しばらく前に、Python から Gmail を使う (1)を書いたが、その補足。Python で IMAP を扱うときに参考になるのは、PyMOTW - imaplib - IMAP4 client library。これを見ると、だいたいの操作がわかる。加えて、Accessing IMAP email accounts using telnet. を見ると telnet でアクセスしたときの操作もわかるので理解が深まるかなと。【送料無料】The Book of IMAP: Building a Mail Server with Courier and Cyrus[洋書]価格:7,487円(税込、送料別)
2011.08.21
コメント(0)
Python をインストールするときに、あれこれモジュールをインスールするのが面倒なので、最近は、 python(x,y) を使っていたのだが、Enthought Python も無償版をまた出すようになっていた のね。Enthought Python が新しくなった (2008.05.04) のころにはEnthought Pythonを使っていたのだが、その後、無償版がなくなってしまったので、Python(x,y) を使うようになったのだが、これからどうしようかな。Enthought Python は、Python 2.7.x 系、python(x, y) はまだ、Python 2.6.x系。Python(x,y) は、現状 Python 2.6.6.1 だが、2.7.2.0 が 7月末にリリースされる予定 のようで、来月になれば、この差は気にする必要はなくなるだろう。ちなみに、Enthought Python は、現状このようなパッケージやツールが含まれている。FREE edition の方には含まれていないものもあるのか。python(x, y) は、このようなものが含まれている。python(x, y) が Python 2.7.x 系になったら、冷静に比較してみるかな。
2011.07.10
コメント(0)
Python コア開発のニュースや身近な話題が扱われているブログ Python Insider を眺める。Python Insider 日本語版 もすでにできているので日本語でも読める。2011年5月6日金曜日 Python Insider 翻訳プロジェクトこのブログのコンテンツは全世界の Python コミュニティに役立つように、なるべく多くの人たちに読んでもらえるようにすることが優先事項の1つだと考えています。私たちの取り組みをもっと拡大するために、他の言語へ翻訳したブログを作成する翻訳チームを編成しました。いま 日本語 と スペイン語 に翻訳されたブログが進められています。すでに、2011年5月9日月曜日 ルーマニア語と中国語 (簡体字) の翻訳、2011年5月20日金曜日 ポルトガル語、ドイツ語、韓国語、中国語 (繁体字) の翻訳 と、多数の言語にも翻訳される体制になっている。Python 3.3 で導入されるデバッグに役立つ faulthandler モジュール とかもできているのねぇと思ったら、UNIX 上では、例えば、 SIGUSR1 シグナルを使えます。 kill -USR1 <pid> は、カレントのトレースバックをダンプします。この機能は Windows 上では使えません。その仕組み上 Windows では使えないのが残念だが、Linux 上でサーバープロセスを動かしておいて、任意のタイミングでカレントのトレースバックをダンプできるとか便利かもしれない。そういえば、Python 3.3 から OS/2, Windows 2000, VMS のサポート終了へ で Windows 2000 もサポート終了らしい。Python も最近では、日本人のユーザーがだいぶ増えて、こういうものも日本語でも読めるようになったのが嬉しい。翻訳をやっている方々には感謝。
2011.05.29
コメント(0)
Python から Gmail を使う方法についてまとめておく。Gmail を使ってメールを送信する標準ライブラリの smtplib を使って送信することができる。# -*- coding: utf-8 -*-import smtplibfrom_address = 'your_email_address@gmail.com'to_address = 'to_mail_address@gmail.com'message = 'Message to send.'# Gmail のユーザー名とパスワードusername = 'your_username'password = 'your_password'# メールを送信するserver = smtplib.SMTP('smtp.gmail.com:587')server.ehlo()server.starttls()server.ehlo()server.login(username,password)server.sendmail(fromaddr, toaddrs, msg)server.quit()でも、これだと MIMEエンコードしてくれないよねということで、send a multipart email via gmail's SMTP server (Python recipe) を使えば、headers = dict()headers["Subject"] = "これはテストですよ"headers["To"] = ["to_address1@example.com", "to_address2@example.com"]headers["From"] = "Your Name <your_address@gmail.com>"password = "your_password"body = u"""今日の天気は雨でした。--民主党は滅びよ!"""email_it_via_gmail(headers, text=body, password=password)みたいに、簡単に Gmail でメールを送信することができる。encode も引数に追加して、iso-2022-jp でも送れるようにするとかしてもよいかもね。ちなみに、これを使って text=body ではなく html=body とすれば、HTML メールも送信できるように作られている。パスワードなどのパラメータをスクリプトから切り離したければ、Python Gmail script (smtp) (Python recipe) のように ConfigParser を使うとか、gmailを、Pythonスクリプトでメールサーバとして使うtips のように yaml を使うとかすればよいだろう。その他、Pythonでメールを送信したい人のためのサンプル集なども参照。と、ここまではよいとして、Gmail 上のメールを取り出して何かしたいとかいうこともあると思う。ということで、次は、IMAP を使ってアクセスしてみる。Gmail に IMAP でアクセスするとりあえず Gmail の IMAP の開始方法 の設定をしてあるのを前提とする。import imaplibfrom email.header import decode_header gmail = imaplib.IMAP4_SSL('imap.gmail.com', 993)gmail.login('your_address', 'your_password')で、ログインすることができたら、あとは、あれこれ操作すればよい。受信トレイに対して何かするなら INBOX を select してから、あれこれする。とりあえず、未読の数を数えてみる。さらに、ひとつ、メールを取り出してみる。# 受信トレイを選択gmail.select('INBOX')# 未読のカウントstatus, response = gmail.status('INBOX', "(UNSEEN)")unreadcount = int(response[0].split()[2].strip(').,]'))print unreadcount# 受信トレイから、1つめのメールを取り出してみる。status, count = gmail.select('Inbox')status, count = gmail.select()status, data = gmail.fetch(count[0], '(UID BODY[TEXT])')print data[0][1]# デコードしないとだめだね# サブジェクトを表示してみる_,[data] = gmail.search(None,'ALL')for i in data.split(' '): _,sub = gmail.fetch(i,'(BODY[HEADER.FIELDS (SUBJECT)])') # デコードして表示してみようか decoded = decode_header(sub[0][1].strip())[1] print unicode(decoded[0], decoded[1])gmail.close()gmail.logout()次に続く。
2011.05.22
コメント(0)
地道に、Python 3 に対応するモジュールが増えてきたのね。NumPy, SciPy, matplotlib が対応するようになってきているようなので(どの程度安定的に使えるのか、まだ見ていないが)、だんだんと Python 3 を実際に使える日が近づいてきたように感じる今日この頃(まだ、ほしい物が全部そろうわないけれど)。matplotlib on Python 3 thanks to Cape Town groupLast month the Cape Town Python Users Group got together again for a weekend porting session, this time on matplotlib. They brought together 8 people to knock out one of the larger roadblocks in wider adoption of Python 3 now that NumPy and SciPy are out of the way, and they did a great job pushing it forward.Windows のバイナリは、Unofficial Windows Binaries for Python Extension Packages にあるのを使わせてもらうと楽かな。GUIに関しては、pyQt は、PyQt v4.5 Released(5 June 2009) で Python 3 に対応しているようだが wxPython は次世代まで対応しないのかな。Tentative wxPython Roadmapを見ると、Python 3.x support: (unknown)。当面の間、GUIをつけるなら TkInter か、PyQt ということになりそう。PyCon 2011: Interview with Lennart Regebro - “Porting to Python 3”Python 2からPython 3への移行PyPI登録著名モジュールのPython3対応状況が一目で分かる Python 3 Wall of ShamePython 3 Wall of ShamePython拡張ライブラリ生成ツールのPython 3.0対応状況Python3.0 への移行準備まあ、なんにせよ、新しい仕事が当面忙しいので、あまり遊んでいる時間もなく、新しいことはできない状態かな。昔は、忙しい時ほど新しいことをやりたくなったものだが、最近は、とりあえず暇があったら寝る。春眠暁を覚えずというより、年食ったなぁという感じ。
2011.04.10
コメント(0)
なんとなく、The Mighty Dictionary (#55) を見たら、とても面白かった。ちなみに、PyCon2010のビデオなのですでに見ちゃった人は多いかもしれない。PyCon 2011 も少し前に終わっていることだし (March 7th ? 15th)、新しいのも時間を見つけてみてみようかな。Youtube で PyCon2011 のビデオを探す。そういえば、PyCon mini JP のもぜんぜんまだ見てないや。PyCon mini JP の動画集。最近、こっち系統の動画見てなかったものな。というのはさておき、The Mighty Dictionary (#55) は、Python の Dictionary についての理解を深めたければこれを見るべしだな。へぇー、そういう風になっていたんだと、普通の人なら思うはず。普段から Pythonを実装レベルで見ているような、その手の人であれば、そんなこと知らなかったの?って言うかもしれないけど。ちなみに、次の質問に答えられない人であれば、見る価値はあると思う。質問には Yes, No だけでなく、その理由もね。Q1. dictionary への登録と取り出しは、常に一定の時間で行われるか否か。Q2. 同じ Key の数であれば、登録と取り出しは、常に一定の時間で行われるか否か。Q3. 同じ Key の数であれば、使用するメモリの大きさは、常に一定であるか否か。Q4. 5つの単語を dictionary 登録したとき、values() で取り出した値は、単語が同じであれば登録順に関わらず、常に同一の順序で取り出されるか否か。もう少し、質問追加。Q5. Key の登録時に、突然、平均値より長い時間がかかったき、その理由はどんなものが考えられるか。Q6. 多くの Key を削除したにも関わらず、使用メモリが小さくならない理由としてどんなことが考えられるか。Q7. Q5 の状態のとき、dictionary の使用メモリを小さくするにはどうしたらよいか。Q8. '/usr/share/dict/words' を dictionary に登録したとき、もっとも、速く key に対する value を取り出す時間と、もっとも、遅い時間とではどの程度の差がつくか。ビデオを見ている時間がない人は、The Mighty Dictionary (HTML) でプレゼンの中身を読むだけでおもしろいと思う。Understanding the Python GIL (#82) とかも、面白いよ。思わず笑っちゃう。プレゼンが始まってすぐに落ちは見えるんだけど、それでも笑っちゃう。お約束の笑い。時間がない人は、Understanding the Python GIL (pdf)と Understanding the Python GIL by David Beazley。The Python GIL Visualizedを見ると、どういう具合か一目でわかる。Pedro Kroger: Python videos のあたりにおもしろいビデオへのリンクがある。ビデオじゃないけど Google's Python Class とかもあったのね。
2011.03.25
コメント(0)
Think Stats: Probability and Statistics for Programmers(by Allen B. Downey) という本が、オンラインで Creative Commons Attribution-NonCommercial 3.0 Unported License で公開されている。Statistical thinking for programmersDescriptive statisticsCumulative distribution functionsContinuous distributionsProbabilityOperations on distributionsHypothesis testingEstimationCorrelation平均、分散、ヒストグラム、プロットと、基本的なところからはじまって、段階をおって構成されているので、いいなぁと思って、ダウンロードしてあるが、まだ読んでない。
2011.03.21
コメント(0)
都道府県別環境放射能水準調査結果をscrapingするの法 または PDF をスクレイピングするの法 を見ると、http://www.mext.go.jp/a_menu/saigaijohou/syousai/1303723.htmこのあたりからデータを取得できるわけだが、なぜか PDF なので、うんざりする。こんなもんどうみても excel かなにかでつくってるんだから生データを提供しろといいたい。と、文句言いながら、スクレイピングしている方がいらっしゃる。pdftotext などのコマンドをつかうのがオススメ。今だと、poppler というライブラリが日本語もあつかえてすばらしすぎるので、これをつかうとよい。これは Perl/Python/Ruby のバインディングがあるので、それをつかってもよいがこういう場合、ライブラリなどでがんばって PDF を解析するのはわりと時間の無駄となる場合がおおい。Poppler (Wikipedia)poppler.freedesktop.orgXpdf と popplerまあ、実際にデータを使おうとすると、使いにくいものって多い。米国の場合は、いろいろな研究機関が政府の下で情報提供しているから、ちゃんと IT 活用しているのよね。以前 SEC、XBRL データの決算情報サービスとかとりあげたけど。FinancialExplorer の こんなのね。そいうや、Internet Explorer 9 出てるけど、関係ないw 一応ついでないので Internet Explorer 9 の新機能。いや、日本はまだ[Internet Explorer 9 製品候補版] のままね。「Internet Explorer 9」正式版が公開、日本語版は地震の影響で公開延期。Toolkit to Disable Automatic Delivery of Internet Explorer 9これ、覚えとこう。話がそれたが、Using pyearthquake to plot Japan USGS earthquake data into the near real-time MODIS satellite imagery では、USGS や MODIS のデータを使って先日の地震のデータをプロットしてみるというのをやっている。公開されているデータから、こんなものが簡単にできちゃうのね。Permanent Link to Exploring real-time Haiti USGS Earthquake data with near real-time MODIS Aqua+Terra satellite imagery using Pythonなども参照。データの取得からプロッティングまでが簡単にできるような枠組みができている。まぁ、この分野は、比較的データの公開が進んでいる分野なんだろうけど、ここから取り出して自分で処理して視覚化してというところの敷居が「ちょっと」高いかなぁ。The 2011 off the Pacific coast of Tohoku Earthquake-Portal-地震に関するファクト/データ情報源気象庁 地震・津波防災科学技術研究所 Hi-net 高感度地震観測網防災科学技術研究所 強震ネットワーク Kyoshin Net東京大学地震研究所 観測開発基盤センター 地震データちなみに 国立国会図書館 リサーチ・ナビで原発について調べてみると
2011.03.21
コメント(0)
音声読み上げTwitterクライアントできたしかし、NVDAに付属している Open JTalk をベースとした日本語音声合成エンジンはなかなかのものである。NVDAのソースをちょっと見てみると、どうやら簡単に日本語音声合成エンジンを利用できそうだ。というわけで、早速 ymotongpooのTwCmdというコマンドライン版Twitterクライアントに組み込んでみた。あまり実用的ではないが、ちゃんとTLを日本語で読み上げてくれる。とあったので、久々、音声に興味が行く。以前、しばらくの間 VoiceText の Misaki を使うのに、電子かたりべプレイヤー の「高品質サービス」の契約結んで使っていたのだけれど、定期的に料金を払う必要があるのでやめてしまった(なんとなく音声合成を試す (2008.12.28) を書いた時期に使っていた)。ちなみに、アクト・ツー様のRSSニュース、Twitter読上げアプリに採用されました。 らしい。一太郎2011 の 詠太を含むパッケージを買うという手もあるか。でも、もう一太郎離れしちゃったのだよなぁ。VOICEROID+ 民安ともえ とか、VOICEROID+ 鷹の爪 吉田くん あたりもありだろうが、ちょっと癖が強すぎて...。【送料無料】VOICEROID+ 民安ともえ価格:7,839円(税込、送料別)とりあえず試してみるかと、まずは Open JTalk が使われている NonVisual Desktop Access (NVDA) をダウンロード。使ってみたら、思ったよりもよい。次に、上記の TwCmd も動かしてみた。一定時間ごとに自動的に読み上げさせるようにするとかしてもよいかな。ソースを見ると、なるほど簡単に Open JTalk が呼び出せるようになっている。必要なところだけ抜き出すと、下のような感じ。# -*- coding: utf-8 -*-import timefrom synthDrivers import _nvdajp_jtalk_nvdajp_jtalk.initialize()WAIT = 0.05texts = ["とてもおなかがすきました。", "何を食べようかなぁ。"]try: for text in texts: _nvdajp_jtalk.speak(unicode(text)) time.sleep(len(text)*WAIT) _nvdajp_jtalk.stop()except Exception, e: print eいいかもしれない。目が疲れているときは、音声で聞きたくなるのだな。でも、音声合成の声は長時間聴くと疲れるのが常。長時間しゃべらせて自分の疲労度をみる人体実験してみるかな。Python からパラメータとか調整するのはどうするのかな。それもちゃんとソース見て調べてみるか。何はともあれ、これはけっこう嬉しい。
2011.02.06
コメント(0)
wxPython: Eguid ? Editra Gui Designer で マルチプラットフォーム対応のテキストエディタ「Editra」 の作者 Cody Precord さんが、Editra Gui Designer なるものを開発し始めたことを知る。ちなみに、Cody Precord さんは、"wxPython 2.8 Application Development Cookbook" の著者でもある。Eguid - Editra Gui DesignerwxPython-dev: Interface Builder Tool を見ると、アイデアを練っている段階なので、すぐに使えるところにはいかないだろうけど、どんなやりとりがされて、どんなものに仕上がっていくかというのをウォッチすると楽しいかもね。というか、日本人も参加して、日本語で問題がでないようなものになってくれると嬉しかったりしてと他力本願モード。こんな風にちゃっちゃと GUI プログラミングができるようになると嬉しいのにね。Python の場合、現状はこのあたりだろうけど、開発が止まってしまっていたり、いまいちなのだよね。Boa constructorPythonCardXRCedちなみに、Editraはけっこうよいなぁと思ったのだけれど、インラインで日本語入力できないのね。高機能なテキストエディタEditraと日本語入力について、wxStyledTextCtrlでの日本語入力に難がある件について など参照。で、Editra 日本語入力 その2、wx.stc.StyledTextCtrlで変換候補を正しく表示。Windows 上ではなんとかなるのか。でも、ちょっと手間がかかるな。PyShell なんかも、手を入れないと編集中の Pythonのプログラムを実行したときに日本語の入出力で問題あるのだよなぁ。関係ないけど、Android 端末を何か持つかなぁと思う今日このごろ。android-scripting 使えば、Python でもアプリが作れるのね。SL4A Video Help を見る。こんな動画もあった。ところで、Android も、IPA、Androidを標的とするボット型ウイルス「Geinimi」への注意を呼びかけ とかいう時代になってるのね。ついで。まったく関係ない話だが、The Evolution of a Python Programmer おもしろい。
2011.01.23
コメント(0)
wxPython 入門の続きは、ちょっとおやすみ。日本語係り受け解析システムといえば、奈良先端大松本研究室で開発された CaboCha があるが、何かと面倒なので、もっと簡単に係り受け解析ができないかということで、Yahoo! JAPAN のテキスト解析 日本語係り受け解析 を使うという手がある。「24時間以内で1つのアプリケーションIDにつき50000件のリクエストが上限」、「1リクエストの最大サイズを4KBに制限」という制限があるので大量に使う場合は困るだろうが、そこに収まる範囲であれば、便利だろう。これを Python から簡単に使えるようにするために、 Yahoo日本語係り受け解析APIのPythonラッパー を公開されている方がいらっしゃったので、ちょっと試してみた。使うためには、Yahoo! JAPAN デベロッパーネットワーク で、アプリケーションID を予め登録しておく必要がある。daservice.py をダウンロードして、site-packages に置いておくか、カレントディレクトリに置いておく。# -*- coding: utf-8 -*-from daservice import DAServiceappid = 'アプリケーションID をここに入れる'da = DAService(appid)for chunk in da.getChunkList('尖閣諸島は日本の領土です。'): print chunk, "->", chunk.dependenceChunkこれを実行すると、尖閣諸島は -> 領土です。日本の -> 領土です。領土です。 -> Noneのように、出力される。Windows のプロンプト上で実行するなら、print unicode(chunk), "->", unicode(chunk.dependenceChunk)とかして文字化けしないようにしてもよし( UTF-8 でそのまま出力すると文字化けして表示されるので )。ついでなので、wxPython で簡単な GUI を付けてみる。# -*- coding: utf-8 -*-import wxfrom daservice import DAServiceappid = 'Yahoo API のアプリケーションID をここに入れる'class KakariukePanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) # text control self.textField = wx.TextCtrl(self, pos=(10,10), size=(400, 50)) self.logger = wx.TextCtrl(self, pos=(10,70), size=(400,300), style=wx.TE_MULTILINE|wx.TE_READONLY) # ボタン self.post_button =wx.Button(self, label="解析する", pos=(410, 10)) self.clear_button =wx.Button(self, label="クリア", pos=(410, 70)) # イベント self.Bind(wx.EVT_BUTTON, self.OnClear,self.clear_button) self.Bind(wx.EVT_BUTTON, self.OnPost, self.post_button) # 係り受け self.da = DAService(appid) def OnClear(self,event): self.logger.Clear() self.textField.Clear() def OnPost(self,event): text = self.textField.GetValue() self.logger.AppendText("【原文】 %s\n\n" % text) for chunk in self.da.getChunkList(text): result = "%s -> %s\n" % (chunk,chunk.dependenceChunk) self.logger.AppendText(result) self.logger.AppendText("\n") self.textField.Clear()app = wx.App(False)frame = wx.Frame(None,title="係り受け解析", size=(520,440))panel = KakariukePanel(frame)frame.Show()app.MainLoop()ちなみに、今、 MASHUP AWARDS 6 が応募中みたいね。私は応募していないし、応募予定もなしだけど。締切り 11月8日。応募作品を見る と、143個応募されている。
2010.10.24
コメント(0)
wPython.org の Getting Started をサカナに第十二弾。Getting started with wxPython でいうと、1 と 2 が終わって、3.Woking with Windows の 3.2 Sizer あたりの話題を引き続き。Getting Started のソースコードの例を見てみる。Sizer を使った箇所だけを抜き出してみる。(Frame.__init__ の中の記述から)self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)self.buttons = []for i in range(0, 6): self.buttons.append(wx.Button(self, -1, "Button &"+str(i))) self.sizer2.Add(self.buttons[i], 1, wx.EXPAND)# Use some sizers to see layout optionsself.sizer = wx.BoxSizer(wx.VERTICAL)self.sizer.Add(self.control, 1, wx.EXPAND)self.sizer.Add(self.sizer2, 0, wx.EXPAND)#Layout sizersself.SetSizer(self.sizer)self.SetAutoLayout(1)self.sizer.Fit(self)ここでは、sizer2 として、水平方向に部品を並べるボタン配置用の BoxSize を作り、そこに Button1 から Button6 6つのボタンを追加。さらに、垂直方向に部品を並べる BoxSizer を作って、control と sizer2 を追加している。これを実行すると、次のようになる。ウィンドウの大きさをいろいろ変えてみて実感してみる。self.sizer.Add(self.sizer2, 0,..) なので、縦方向のサイズは起動時と変わらないが、control の方は 1 なので、縦に伸ばせば、それに応じて広がる。ボタンは、size2 の中でリサイズするように指定されているので、横に広げたときに、横幅いっぱいに広がってくれる。パネルにラベルを付けてみる"Getting Started" には、入力フォームの値を wx.Validator でチェックして云々の話が若干書かれていているのだが、実例まで踏み込んでないのでここでは飛ばしておく。実際のアプリケーションを作ったら、入力フィールドで整数値の 0~99 を指定したときには処理をするけれど、それ以外であればエラーを出して云々とかいう処理が必要になって、そういう場合に、wx.Validator を使えるねというところで終わって、次に進む(そのうち、実例で扱う)。参考にしているのは、A Working Example: Our first label within a panel のあたりから。ここでは Panel と StaticText が出てくる。まずは StaticText で、指定した位置にユーザーが書き換えできない固定の文字列を表示する。Getting Started では Frame に StaticText を配置するようなコードになっているのだが、パネル (Panel)を作って、そこに配置してみた。# -*- coding: utf-8 -*-import wxclass ExamplePanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) self.SetBackgroundColour("silver") wx.StaticText(self, label="ラベル1 :", pos=(10, 10)) wx.StaticText(self, label="ラベル2 :", pos=(100, 10)) wx.StaticText(self, label="ラベル3 :", pos=(200, 10)) wx.StaticText(self, label="ラベル4 :", pos=(10, 30)) wx.StaticText(self, label="ラベル5 :", pos=(100, 30), size=(20, -1)) wx.StaticText(self, label="ラベル6 :", pos=(200, 30), size=(-1, 10)) wx.StaticText(self, label="ラベル7 :", pos=(10, 60), size=(200,-1)) wx.StaticText(self, label="ラベル8 :", pos=(30, 60)) wx.StaticText(self, label="ラベル9 :", pos=(200, 60)) app = wx.App(False)frame = wx.Frame(None)panel = ExamplePanel(frame)frame.Show()app.MainLoop()pos で x, y 座標を指定している。サイズは横幅だけ指定して、縦は、-1 で自動になっているので、フォントサイズに応じて、それが表示できるだけの高さが確保される。size は指定しなくても動く。ラベル5は、必要な横幅を文字幅より少ないポイント数で指定してみた。右側が表示しきれず途切れる。ラベル6 は縦幅を指定し、必要な文字丈より少なくしてみた。下の方が途切れる。size は (-1, -1) で自動計算にしておけば、無指定と同じで途切れることはない。ラベル7と 若干重なる位置にラベル8は置いてみた。あとから置いたラベル8が強い。ラベル7は sizeで必要幅以上を指定しているが関係なく上書きされる。ちなみに、wxPython のドキュメントによると、パネル(panel) は、さまざまなコントロールを配置するために使われるウィンドウで、通常フレーム上に配置される。親クラスの wxWindow クラスに最小限の機能を追加したもので、見た目も機能も Dialog に似ているが、parent はどのような window クラスも親とすることができるところが違い、柔軟性があるとのこと。
2010.10.14
コメント(0)
wPython.org の Getting Started をサカナに第十一弾。Getting started with wxPython でいうと、1 と 2 が終わって、3.Woking with Windows の 3.2 Sizer あたりの話題から。wxPython 入門 (1) フレームとアプリケーションwxPython 入門 (2) テキストコントロールwxPython 入門 (3)文字色、背景色とフォントwxPython 入門 (4) メニューとステータスバーwxPython (5) イベントとバインドwxPython (6) (5) のソースコードwxPython (7) プログラムの終了とダイアログの表示wxPython (8) ファイルを開くダイアログwxPython (9) (8) のソースコードwxPython (10) ウィンドウ配置の概要Sizer を使ったレイアウトを配置Frameの中に、wx.BoxSizer を使ってボタンを3つ、水平方向に並べてみる。# -*- coding: utf-8 -*-import wxclass MainWindow(wx.Frame): def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(200,-1)) # ボタンを作成 self.button_cupnudle = wx.Button(self, wx.ID_ANY, "カップヌードル") self.button_bigmac = wx.Button(self, wx.ID_ANY, "ビッグマック") self.button_gyudon = wx.Button(self, wx.ID_ANY, "牛丼") # 水平方向に並べる BoxSizer を作成 self.sizer = wx.BoxSizer(wx.HORIZONTAL) # ボタンを BoxSizer に追加 self.sizer.Add(self.button_cupnudle) self.sizer.Add(self.button_bigmac) self.sizer.Add(self.button_gyudon) # レイアウトを行う self.SetSizer(self.sizer) self.SetAutoLayout(True) self.sizer.Fit(self) # Frame を表示する。 self.Show() app = wx.App(False)frame = MainWindow(None, "Sizer サンプル")app.MainLoop()ウィンドウサイズを広げると次のようになる。self.sizer.Add(self.button_xxxx) でボタンをサイザーに追加に追加していき、SetSizer()でサイザーをセットし、SetAutoLayout()でレイアウトの自動化の指定を行い、Fit()でサイザーを Frame サイズにフィットさせる計算をする。そして Show() でフレーム表示。sizer.Add するときには、オプションを指定することができる。self.sizer.Add(self.button_xxx, 0) のように指定した場合、 0は、リサイズをするかどうか。0 にするとリサイズせず、 0 より大きい値を設定するとリサイズする(指定がないときは 0 を指定したのと同じ)。上記の例に変更して、1 を指定すると、サイズを広げたときに、次のようになる。試しに、牛丼だけ 0、それ以外は 1 にして広げてみると次のようになる。ウィンドウを広げても、牛丼だけサイズが変わらない。カップヌードルとビッグマックはウィンドウの幅に合わせて広がる。Size にさらにオプションを付けてみる。self.sizer.Add(self.button_xxx, 1, wx.EPAND)としたものが次の画像。ウィンドウのサイズにあわせて、縦横ともにボタンが広がるようになる。フレームを広げると、それに応じてボタンのサイズも大きくなる。BoxSizer が Frame にフィットするようにしているので、ボタンはフレームの中で隙間なく均等に広がる。ここでまた、牛丼だけ、self.sizer.Add(self.button_xxx, 0, wx.EPAND) とすると次のようになる。ボタンサイズ自体は、フレームにフィットしているものの、牛丼の横幅は、最初のままでリサイズされない。ちなみに、self.sizer = wx.BoxSizer(wx.HORIZONTAL) のところを、self.sizer = wx.BoxSizer(wx.VERTICAL) とすれば、縦方向に並ぶようになる。wx.EPAND が指定されているところは、いろいろな値をとることができる。割り当てられた横幅に対して、アイテムのをどちらの縁に合わせるかを指定する。ALLは HORIZONTAL または、VERTICAL の指定方向だけで、wx.EXAND の場合は、指定方向に関係なく全方位。wx.TOPwx.BOTTOMwx.LEFTwx.RIGHTwx.ALLアイテムをすべての方向に対してフィットさせる。wx.EXPAND縦横の比率を維持したまま、できるだけ大きいサイズでフィットさせる。wx.SHAPED自動的に最適値として計算された最小の大きさのまま固定。wx.FIXED_MINSIZE割り当てられたスペースの中での配置方法の指定。wx.ALIGN_CENTERwx.ALIGN_LEFTwx.ALIGN_RIGHTwx.ALIGN_TOPwx.ALIGN_BOTTOMwx.ALIGN_CENTER_VERTICALwx.ALIGN_CENTER_HORIZONTAL複数のフラグを指定する場合は、wx.FIXED_MINSIZE|wx.ALIGN_CENTER のように「 | 」でフラグをつないでいく。ちょっと極端な例だが、もし、次のように指定すれば、self.sizer.Add(self.button_cupnudle, 1, wx.SHAPED|wx.ALIGN_TOP)self.sizer.Add(self.button_bigmac, 0, wx.FIXED_MINSIZE|wx.ALIGN_CENTER_VERTICAL)self.sizer.Add(self.button_gyudon, 0, wx.FIXED_MINSIZE|wx.ALIGN_BOTTOM)こうなる。BoxSizer をうまく使えば、ウィンドウサイズを変えたときでも柔軟に対応できそうな感じ。
2010.10.13
コメント(0)
wPython.org の Getting Started をサカナに第十弾。Getting started with wxPython でいうと、1 と 2 が終わって、3 Woking with Windows のあたりから。wxPython 入門 (1) フレームとアプリケーションwxPython 入門 (2) テキストコントロールwxPython 入門 (3)文字色、背景色とフォントwxPython 入門 (4) メニューとステータスバーwxPython (5) イベントとバインドwxPython (6) (5) のソースコードwxPython (7) プログラムの終了とダイアログの表示wxPython (8) ファイルを開くダイアログwxPython (9) (8) のソースコードウィンドウ配置の概要ここから、ウィンドウをどのように扱い、配置するかなどの話が始まる。これまでは、Frame 、TextCtrl 、MenuBar、Menu, StatusBar, MessageDialog, FileDialog 程度の部品しかつかっていなかったが、実際にアプリケーションを作るとなると、もっとたくさんの部品を使う必要があるのは言うまでもない。さまざまな部品は、wxWindow のサブクラスになっていて、実にたくさんのものがある。たとえば、フレームにツールバーを追加するための、wx.ToolBar や、wx.Control オブジェクトを部品として、複数のオブジェクトを配置するための入れ物となるパネル (wx.Panel)、ユーザが直接変更できない文字列を表示するための wx.StaticText、ドロップダウンリストから選択もできるし直接文字列の入力も可能な wx.ComboBox をはじめとして、いろいろなものがあるので、じっくり覚えていかなければならない。それと同時に、どのようにしたら部品をウィンドウ上に配置していくことができるのかも覚えなければならない。たとえば、図のようにアプリケーションのウィンドウとして wx.Frame、そこに wx.MenuBar と wx.Panel を配置し、さらに wx.Panel の中に wx.StaticText や wxTextCtrl などの部品を配置していくというイメージ図になる。図は、Getting started with wxPython より拝借。実際には、どのように部品を視覚的に配置するのか。次のような方法が考えられる。がんばってピクセル単位で、どの位置にどの部品を置くかを決める。wx.LayoutConstraints を使う。Delphai-like な LayoutAnchors を使う。wxSizer のサブクラスを使う1. は、あまりに面倒だし、プラットフォーム(OS)が変わったときにどう対応するか、フォントサイズが異なるときにどうするか等々、融通が利かないのでお勧めできないとされる。2. は複雑で使うのが難しい。3. wx.LayoutConstraints を使いやすくしてくれるので候補には入る。4. Getting Started で取り扱うのはこれ。Started Guide を書いた人が慣れ親しんでいるということで、記事は wx.Sizer がメインになる。ここで Window Layoutを見てみると、wxLayoutConstraints の例なども載っている。b = wxButton(self.panelA, 100, ' Panel A ')lc = wxLayoutConstraints()lc.centreX.SameAs (self.panelA, wxCentreX)lc.centreY.SameAs (self.panelA, wxCentreY)lc.height.AsIs ()lc.width.PercentOf (self.panelA, wxWidth, 50)b.SetConstraints(lc) その名のとおり、部品の制約条件を指定して配置するのだな。ボタンはパネルの真ん中に位置し、パネルは親ウィンドウに対して、幅50% にする等、部品の位置関係を中心に記述していくようなもののようだ。確かに大変そう。"Window Layout" の "4. Resources " は、XRCed のようなリソースエディタを使う話だと思うが、wxPython GUI リソースエディタ XRCedや XRCedの使い方 XRCedは一癖あります など参照。こういうものを使うと、GUI で部品の配置ができるから楽かもしれないですねと言いつつ、まずは、Size を学習するのでありました。XRCed や wxGlade、Boa Constructor, PythonCard などビジュアル系はそのうち扱うが、とりあえず無視してゴリゴリコードを書く系のみ見ていく。"Getting Stated"の Sizer の話に戻る。Sizer で部品を配置するSizer は、wx.Sizer のサブクラスで、フレームの中で部品をどのように配置するかを自動的に計算して配置してくれる。Tkinter とか使っていた人には、pack していくイメージを思い浮かべるとよいのかな。視覚的な部品のサイズが適切になるように自動的に計算してくれる。ルールに従って、部品の位置を決めてくれる。フレームのサイズが変更されたときに、動的に部品のサイズを変更したり、再配置してくれる。Sizer には、いくつかの種類がある。wx.BoxSizer: 水平方向(HORIZONTAL)か、垂直方向(VERTICAL) の直線状に部品を配置する。wx.GridSizer: 視覚的な部品をグリッドライクな構造で配置する。wx.FlexGridSize: wx.GridSIzer に似ているが、より柔軟なレイアウトを取ることができる。Sizer を使うときには、配置の対象となる wx.Window オブジェクトを sizer.Add(window, options...) のように配置対象のリストに追加し、その後、それらの部品を配置する。 sizer.AddMany(...).もある。イメージ的にいうと、箱の中に、縦方向に部品を詰め込んで並べていくか、横方向に詰め込んでいくかという感じ。Sizer は入れ子にできるので、たとえば、水平方向に3つのボタンを並べる wx.BoxSizer を作って、さらに同じものを作って、2つの BoxSizer を別の BoxSizer に垂直方向に並べるといったことができる。図は、Getting started with wxPython より拝借。上記は、都合 6つのボタンがあるが、もし、これを1つの Sizer の中で配置しようとするならば、wx.GridSizer を使ってねということになる(6つのマス目に部品を置いていく)。もう少補足として、XRCedの使い方 XRCedは一癖あります の 【3.4】 サイザーに関するルール を参照してみる。【3.4.1】 wxSizer全般に通じるルールwxFrame/wxDialog/wxPanelには唯一の子wxSizerを持つことができる。wxFrame/wxDialog/wxPanelのサイズは子wxSizerにフィットしようとする。wxSizerは複数の子を持つことができる。wxSizerの子になれるのはwxSizerおよびwxPanelとその他のコントロール。wxSizerは親からのサイズ指示がない限りすべての子が収まる最小のサイズになる。wxSizerの子になったものは、wxSizerItemとしての機能が追加される。wxSizerは横方向か縦方向かというレイアウトの方向を持っている。FrameやPanel に、いきなり BoxSizer を 2つ置くとかいうことはできず、まず、Frame や Panel にフィットする BoxSizer を作って、その中に 2つの BoxSizer をつくらなければならないということになるのね。Sizer のドキュメントを次にまとめておく。Type Sizerwx.BoxSizerwx.StaticBoxSizerwx.BoxSizerwx.GridSizerwx.FlexGridSizerwx.GridBagSizer今日はここまでで、実例は次のエントリーで。
2010.10.13
コメント(0)
wPython.org の Getting Started をサカナに第九弾。Getting started with wxPython でいうと、2.4 まで終わらせて、とりあえず、ここまで書けるようになったというソースコード。メニューは、__init__ の中に詰め込まないで別のメソッドにまとめた方がいいかもねとか、そういうことまではしていないので __init__ がやけに長いので、SetupMenu メソッドを作ってまとめておくことにした。ということで、ここまでのソースコードのまとめ。wxPython 入門 (1) フレームとアプリケーションwxPython 入門 (2) テキストコントロールwxPython 入門 (3)文字色、背景色とフォントwxPython 入門 (4) メニューとステータスバーwxPython (5) イベントとバインドwxPython (6) (5) のソースコードwxPython (7) プログラムの終了とダイアログの表示wxPython (8) ファイルダイアログとファイルの読み込み# -*- coding: utf-8 -*-import wximport osclass MyFrame(wx.Frame): """ 簡易エディタ """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(400,300)) self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE) # メニューバーを作成する self.SetupMenu() # ステータスバーを作成する self.CreateStatusBar() # 表示 self.Show(True) def SetupMenu(self): # 個々のメニューオブジェクトを作成する # ファイルメニュー、編集メニュ、書式メニュー、表示メニュー、ヘルプメニューの各メニューオブジェクトを作成 file_menu= wx.Menu() edit_menu = wx.Menu() help_menu = wx.Menu() # 各メニュー毎にメニューアイテムを作っていく # ファイルメニュー menuNew = file_menu.Append(wx.ID_NEW, "新規作成 (&N)", "ファイルを新しく作ります") menuOpen = file_menu.Append(wx.ID_OPEN, "開く (&F)", "ファイルを開きます") menuSave = file_menu.Append(wx.ID_SAVE, "上書き保存 (&S)", "編集中のファイルに上書きで保存します") menuSaveas = file_menu.Append(wx.ID_SAVEAS, "名前を付けて保存 (&A)", "新しく名前をつけてで保存します") file_menu.AppendSeparator() # メニューセパレータ menuExit = file_menu.Append(wx.ID_EXIT, "終了 (&X)", "簡易エディタの終了します") # 編集メニュー menuUndo = edit_menu.Append(wx.ID_UNDO, "元に戻す (&U)", "編集を元に戻します") menuCut = edit_menu.Append(wx.ID_CUT, "切り取り (&T)", "選択箇所を切り取ります") menuCopy = edit_menu.Append(wx.ID_COPY, "コピー (&V)", "選択箇所をコピーします") menuPaste = edit_menu.Append(wx.ID_PASTE, "貼り付け (&P)","切り取られた箇所を貼り付けます") # ヘルプメニュー menuHelp = help_menu.Append(wx.ID_HELP, "ヘルプの表示 (&H)", "プログラムのヘルプを表示します") menuAbout = help_menu.Append(wx.ID_ABOUT, "バージョン情報 (&A)", "プログラムのヘルプを表示します") # メニューバーを作成し、個々のメニューをメニューバーに追加していく menuBar = wx.MenuBar() menuBar.Append(file_menu,"ファイル (&F)") menuBar.Append(edit_menu, "編集 (&E)") menuBar.Append(help_menu, "ヘルプ (&H)") # 個々のメニューアイテムを、イベントハンドラーにバインドする self.Bind(wx.EVT_MENU, self.OnNew, menuNew) self.Bind(wx.EVT_MENU, self.OnOpen, menuOpen) self.Bind(wx.EVT_MENU, self.OnSave, menuSave) self.Bind(wx.EVT_MENU, self.OnSaveas, menuSaveas) self.Bind(wx.EVT_MENU, self.OnExit, menuExit) self.Bind(wx.EVT_MENU, self.OnUndo, menuUndo) self.Bind(wx.EVT_MENU, self.OnCut, menuCut) self.Bind(wx.EVT_MENU, self.OnCopy, menuCopy) self.Bind(wx.EVT_MENU, self.OnPaste, menuPaste) self.Bind(wx.EVT_MENU, self.OnHelp, menuHelp) self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout) # メニューバーを Frame にセットする self.SetMenuBar(menuBar) def OnNew(self, event): print "Select New" def OnOpen(self,e): """ ファイルを開く """ # ホームディレクトリを開くようにする self.dirname = os.getenv("HOME") or os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH") # フィルタ文字列のセット filters = 'Python files (*.py;*.pyw) | *.py;*.pyw | txt files (*.txt)|*.txt| All files (*.*)|*.*' dlg = wx.FileDialog(self, "ファイルを選択してください", self.dirname, "デフォルトのファイル名", filters, wx.OPEN) if dlg.ShowModal() == wx.ID_OK: self.filename = dlg.GetFilename() self.dirname = dlg.GetDirectory() f = open(os.path.join(self.dirname, self.filename), 'r') self.control.SetValue(f.read()) f.close() dlg.Destroy() def OnSave(self, event): print "Select Save" def OnSaveas(self, event): print "Select Save As" def OnUndo(self, event): print "Select Undo" def OnCut(self, event): print "Select Cut" def OnCopy(self, event): print "Select Copy" def OnPaste(self, event): print "Select Paste" def OnHelp(self, event): print "Select Help" def OnAbout(self, event): # OK ボタンがついたメッセージダイアログを表示する。 # dlg = wx.MessageDialog( self, "この簡易エディタはサンプルプログラムです。", "簡易エディタ") dlg = wx.MessageDialog( self, "この簡易エディタはサンプルプログラムです。", "簡易エディタ", wx.OK|wx.STAY_ON_TOP) # ダイアログの表示 dlg.ShowModal() # ダイアログの終了時にダイアログオブジェクトを破棄する #dlg.Destroy() self.dlg = dlg def OnExit(self, event): # OK ボタンがついたメッセージダイアログを表示する。 dlg = wx.MessageDialog( self, "簡易エディタを終了してもよいですか", "簡易エディタ", wx.YES_NO|wx.ICON_QUESTION) # ダイアログの表示 response = dlg.ShowModal() # 「はい」なら終了 if response == wx.ID_YES: dlg.Destroy() self.Close(True) # 「いいえ」なら、ダイアログを閉じるだけ elif response == wx.ID_NO: dlg.Destroy()app = wx.App(False)frame = MyFrame(None, '簡易エディタ')app.MainLoop()
2010.10.09
コメント(0)
wPython.org の Getting Started をサカナに第八弾。Getting started with wxPython でいうと、2.3 から 2.4 のあたりの続き。今回は、ファイルを開くダイアログを作ってみる。wxPython 入門 (1) フレームとアプリケーションwxPython 入門 (2) テキストコントロールwxPython 入門 (3)文字色、背景色とフォントwxPython 入門 (4) メニューとステータスバーwxPython 入門 (5) イベントとバインドwxPython 入門 (6) (5) のソースコードwxPython 入門 (7) プログラムの終了とダイアログの表示ファイルを開くダイアログを作ってみるファイルを開くには、OS 標準のファイルを開くダイアログを呼び出してくれる FileDialog がある。独自のダイアログではなくて、OS 標準のものなので、見た目や使い勝手で浮いてしまうことがない。選択したあとに、「開く」ボタンで 終了したかどうか(キャンセルボタンが押されたのではない)を if dlg.ShowModal() == wx.ID_OK: で確認して、その上で、GetFilename() と、GetDirectory() でファイル名とディレクトリ名を取り出す。そして、os.path.join でパス名を完成させる。そして、ファイルをオープンし(open)、read() で中身を読み込み、control.SetValue() でテキストコントロールにセットしている。読み終わったらファイルを閉じ(close)、ダイアログ終了時には、ダイアログを Destroy() で破棄している。 def OnOpen(self,e): """ ファイルを開く """ self.dirname = '' dlg = wx.FileDialog(self, "ファイルを選択してください", self.dirname, "", "*.*", wx.OPEN) if dlg.ShowModal() == wx.ID_OK: self.filename = dlg.GetFilename() self.dirname = dlg.GetDirectory() f = open(os.path.join(self.dirname, self.filename), 'r') self.control.SetValue(f.read()) f.close() dlg.Destroy()そうすると、こうなる。FileDialog の引数は、(self, parent, message=FileSelectorPromptStr, defaultDir=EmptyString, defaultFile=EmptyString, wildcard=FileSelectorDefaultWildcardStr, style=FD_DEFAULT_STYLE, pos=DefaultPosition) wx.OPEN となっているところは、お作法的には wx.FD_OPEN が正しいような気もするが、>>>wx.FD_OPEN1>>>wx.OPEN1定義されている値が共に 1 で同じだから、動く。他の wx.FD_SAVE、wx.FD_OVERWRITE_PROMPT、wx.FD_MULTIPLE、wx.FD_CHANGE_DIR なども、FD_ がなくても、すべて同じ値になっているので問題ないけど。どうなんだろうな。けっこう短縮形を使っていることが多い。Style Guide for wxPython code とか見ても、書いてないし、"Simple is better than complex." で短縮形でよいということかな。デフォルトで開くディレクトリ(DefaultDir) に関しては、self.dirname = os.getcwd() として、プログラムを起動したカレントディレクトリや、self.dirname = os.getenv("HOME") or os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH")等として、ユーザーのホームディレクトリをファイルを開くときの基準にするということもできる。デフォルトファイル(defaultFile) を "" ではなく、"sample.txt" とか入れておくと、ファイル名のところに "sample.txt" が入った上で、ダイアログが開く。ファイルを開くダイアログで選択ファイルの拡張子を指定するここで、指定したファイルの拡張子を指定したいとかいうことになったらどうなるか。たとえば、python のファイルにフィルタをかけたくて、 "*.*" の箇所を変更する。Python のファイルには、*.py と *.pyw にフィルタをかけて表示したい。この場合、次のようになる。dlg = wx.FileDialog(self, "ファイルを選択してください", self.dirname, "", "*.*", wx.OPEN)をfilters = 'Python files (*.py;*.pyw) | *.py;*.pyw'dlg = wx.FileDialog(self, "ファイルを選択してください", self.dirname, "", "*.*", wx.OPEN)とすれば、Python のファイルだけを表示することができる。でも、プルダウンでいろいろな種類を選択したいよねということであれば、 filters = 'Python files (*.py;*.pyw) | *.py;*.pyw | txt files (*.txt)|*.txt| All files (*.*)|*.*' のように "表示1|拡張子1|表示2|拡張子2|表示3|拡張子4" のように複数並べていれてやればよい。これで Python files、txt files, All files がフィルタとして選択できるようになる。 エラー処理がないから、存在しないファイル名を指定されると困る。なので、os.path.isfile でファイルがあるかどうかを確認した上で open しようとか、開けなければエラーメッセージ出しましょうとか、日本語の文字コードがいろいろあるファイルを読み込んだときのことを考えて、コードを変換した上で読み込むとかしたいところかもしれないのだが、ここではやらないで、後の機会に残しておく。文字コードを判定して、codecs.open で開けばよいだけなのだが。 ここまでで、Getting started with wxPython の 2.4 あたりまでをカバーした。2.5 Possible extensions で、いろいろな拡張があるよという存在だけが示されている。Drag and DropMDITab view/multiple filesFind/Replace dialogPrint dialog (Printing)Macro-commands in python ( using the eval function)etc ...このブログでも、これに合わせて、詳細にとりあえず立ち入らず、いったんここで話題を変えることにする(別ネタで扱う予定)。
2010.10.09
コメント(0)
wxPython.org の Getting Started をサカナに第七弾。これまでテキストコントロール (wx.TextCtrl) に文字を表示し、文字色や背景色を変更したり、表示フォントを変更してみた。そして、メニューやステータスバーを付け、さらにメニューイベントに対応した処理をバインドしてというところまでやった。今回は、イベントハンドラーのメソッドの中に少し処理を入れてみる。ひとつは、プログラムを終了するという単純なところと、もうひとつはダイアログを出すところ。Getting started with wxPython でいうと、2.3 から 2.4 のあたり。全部で 12項目あるのでまだまだこのネタは続くのであった。さらに次のネタもみつけてあるので、当面 wxPython 入門は続きそう。wxPython 入門 (1) フレームとアプリケーションwxPython 入門 (2) テキストコントロールwxPython 入門 (3)文字色、背景色とフォントwxPython 入門 (4) メニューとステータスバーwxPython 入門 (5) イベントとバインドwxPython 入門 (6) (5) のソースコードwxPython のプログラムを終了するwxPython で書かれたプログラムを終了するには、コマンドラインから起動した場合には、コマンドライン上で Ctrl-C を入力して強制的に終了させるかw、ウィンドウの右上の × をクリックして終了させることもできる。でも、ちゃんとプログラム独自に終了させることもできるようにしましょうということで、[ファイル]メニュー - [終了] を選択するとプログラムが終了できるようにする。これはいたって簡単。メニューを選択したときに、イベントハンドラーの中で、ウィンドウ(Frame) を Close(True) してやればよい。それだけ。次のものは、単純にするために必要な箇所だけのコード。# -*- coding: utf-8 -*-import wxclass MyFrame(wx.Frame): """ メニューから終了する """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(400,300)) file_menu= wx.Menu() # Exitメニューアイテムのオブジェクト (バインドするときのソース) menuExit = file_menu.Append(wx.ID_EXIT, "終了 (&X)", "簡易エディタの終了します") # メニューバーオブジェクトを作って、そこにファイルメニューオブジェクトを追加 menuBar = wx.MenuBar() self.SetMenuBar(menuBar) menuBar.Append(file_menu,"ファイル (&F)") # イベントに対して、ハンドラとソースをバインドする self.Bind(wx.EVT_MENU, self.OnExit, menuExit) # 表示 self.Show(True) # 終了のためのメソッド def OnExit(self,e): self.Close(True)app = wx.App(False)frame = MyFrame(None, '簡易エディタ')app.MainLoop()終了を選択するとあっさりと、プログラムは終了する。ダイアログを表示する[ヘルプ]メニュー -[バージョン情報] を選択すると、About ダイアログが表示されるようにしてみる。これも同じようにメニューイベントのハンドラを書いてあげる。前回のwxPython (6) (5) のソースコードをベースに追加修正する。ダイアログを表示するのは、wx.MessageDialog。引数は、messageDialog(parent=None, message='', caption='Message', style = wx.OK | wx.CANCEL | wx.CENTRE, pos=wx.DefaultPosition) 。def OnAbout(self, event): # OK ボタンがついたメッセージダイアログを表示する。 dlg = wx.MessageDialog( self, "この簡易エディタはサンプルプログラムです。", "簡易エディタ", wx.OK) # ダイアログの表示 dlg.ShowModal() # ダイアログの終了時にダイアログオブジェクトを破棄する dlg.Destroy()ダイアログのスタイルで、style= wx.YES_NO とすれば、「はい」と「いいえ」のボタンが表示される。何も指定しなければ、style=wx.OK|wx.CANCEL|wx.CENTRE が指定されたのと同じことになるので、「OK」 と 「キャンセル」ボタンが表示される。スタイル (style) は、wx.OK、wx.CANCEL、wx.YES_NO と wx.YES_DEFAULT、wx.NO_DEFAULT、さらに、wx.ICON_EXCLAMATION、wx.ICON_INFORMATION、wx.ICON_HAND, wx.ICON_ERROR, wx.ICON_QUESTION, wx.ICON_INFORMATION, wx.STAY_ON_TOP を組み合わせて指定可能。アイコンの種類を変更したいときは、たとえば、wx.OK| wx.ICON_ERROR と | でつないで指定してやればよい。デフォルトは、ICON_INFORMATION。wx.STAY_ON_TOP を付けてやると、ダイアログが常に一番上のウィンドウとして表示されるので、他のプログラムのウィンドウの下に隠れてしまうということがなくなる。MessageDialog では、Frame やメニューを作るときと違って引数に ID が指定されていないが、これは内部で自動的に id = wx.ID_ANY(実際は -1 だったりもする)で、自動的に ID が割り当てられているから。一番単純には、wx.MessageDialog(self, "メッセージ") だけでも動くが、タイトルキャプションも付けると、wx.MessageDialog( self, "この簡易エディタはサンプルプログラムです。", "簡易エディタ")で、この場合、こうなる。wx.ICON_QUESTION の場合、アイコンが次のようになる。ダイアログを表示するときに showModal() とする。フレームのときは、フレームのときは Show() だったのでちょっと違う。モーダル(Modal) は、このダイアログが表示されている間、ダイアログにフォーカスがあたり、OK か Cancel が押されるまで、他に何もできないように作られているタイプのもの。つまり、この手のダイアログの類を作ったときには、ShowModal() を使う。また、Show() にしても何も表示されない。最後に Destroy() をしないと、OK をクリックすればダイアログは消えるものの、オブジェクトがきちんと破棄されず、MessageDialog が呼び出されるたびに新しいオブジェクトが作られ続ける。つまり、ダイアログのオブジェクトは明示的に破棄しないと、プログラム終了までメモリ内に残ってしまうので注意が必要。OK, Cancel ダイアログを追加してみるダイアログで複数のボタンがあるようなものを表示し、どちらのボタンが押されたかを処理に使いたい場合はどうしたらよいか。ということで、そのサンプルを載せておく。前のダイアログでは OK だけしか表示せず、その返答も捨てていたが、ここでは何のボタンが押されたかを確認したうえで処理する。ShowModal() を呼ぶと、その結果を取れるので、 if dlg.ShowModal() == wx.ID_OK: のような処理を書けばよいことになる(ShowModal() は、wx.ID_YES、wx.ID_NO、wx.ID_CANCEL、wx.ID_OKのいずれかを返す)。終了メニューが選択されたときに、ほんとうに終了してもよいですかと表示して、OK なら終了。Cancel ならダイアログだけを閉じて、メインのフレームに戻るようにしてみる。def OnExit(self, event): # OK ボタンがついたメッセージダイアログを表示する。 dlg = wx.MessageDialog( self, "簡易エディタを終了してもよいですか", "簡易エディタ", wx.YES_NO|wx.ICON_EXCLAMATION) # ダイアログの表示と返答の取り出し response = dlg.ShowModal() # 「はい」なら終了 if response == wx.ID_YES: dlg.Destroy() self.Close(True) # 「いいえ」なら、ダイアログを閉じるだけ elif response == wx.ID_NO: dlg.Destroy()
2010.10.09
コメント(0)
35.4. winsound ? Windows 用の音声再生インタフェース を使っている Python Tuner (電気羊の羊小屋 )を見て、ふと思った。winsound.Beep(周波数:Hz, 鳴らす時間:ミリ秒) で、PCのスピーカーを鳴らすことができる。440Hz といえば A(ラ) の音。基準の周波数。ギターをやっていたころは、よく聴いた音。音叉を咥えてもだえていたなぁ。チューナーの基礎知識 みたいな機械的なチューナーを使ったりもしたが、直接耳で聴くほうが気持ちがいい。440Hz に洗脳されてしまっている。import winsoundwinsound.Beep(440,500)440Hz の倍音は 880Hz。この音のつながりは、時報だ。NHK の時報みたいにしてみようと調べてみる。NHKの時報について を見ると、57秒、58秒、59秒に 440Hz の音を 100ミリ秒ならし、0秒で 880Hz を鳴らすとある。PCで実際にやってみると、100ms だと気持ちよくないので少し伸ばして 150ms にしてみた。import winsoundimport timedef time_signal(): for i in range(3): winsound.Beep(440,150) time.sleep(0.85) winsound.Beep(880,1400)if __name__ == '__main__': times_signal()時報っぽい音に聞こえるかな。でも、880Hz の音を減衰させていくことができないから不自然。だんだんと小さくなって消えて欲しいのだが。。。動作確認できたら、これを 適当なファイル名.pyw で保存して、Windows だったらタスクマネージャに登録して。毎時間時報がなるようにしてみた。拡張子 pyw にしておけば、黒いコマンドプロンプトの画面が表示されずに音が鳴る。ところが、性能が低い PC で動かそうとすると、負荷が高いときに、ちゃんとブツブツになってちゃんとした音にならないときがある。なので、優先順位を上げてやったらどうだろうと調べる。import win32apiimport win32processimport win32con pid = win32api.GetCurrentProcessId()handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, True, pid)win32process.SetPriorityClass(handle, win32process.HIGH_PRIORITY_CLASS) のようにすれば、起動したプロセスの優先順位を高くできる。これを使って、音を鳴らす前に、優先順位を上げておけば、多少はよくなるかなと。Windows の優先順位は次のようになっている。 リアルタイム win32process.IDLE_PRIORITY_CLASS 高 win32process.BELOW_NORMAL_PRIORITY_CLASS 通常以上 win32process.NORMAL_PRIORITY_CLASS 通常 win32process.ABOVE_NORMAL_PRIORITY_CLASS 通常以下 win32process.HIGH_PRIORITY_CLASS 低い win32process.REALTIME_PRIORITY_CLASS優先順位の定数の名前を覚えるのも大変なので、下のようにして 0 ~ 5 の値を指定すると、優先順位が上下できるというようにするとよいかな。起動したあとに、優先順位を高に上げて、一呼吸待ってから音を鳴らし始める。毎時 59分55秒にタスクをしかける。 # -*- coding: utf-8 -*-import winsoundimport time## http://code.activestate.com/recipes/496767/ (r1)def setpriority(pid=None,priority=1): """ Set The Priority of a Windows Process. Priority is a value between 0-5 where 2 is normal priority. Default sets the priority of the current python process but can take any valid process ID. """ import win32api,win32process,win32con priorityclasses = [win32process.IDLE_PRIORITY_CLASS, win32process.BELOW_NORMAL_PRIORITY_CLASS, win32process.NORMAL_PRIORITY_CLASS, win32process.ABOVE_NORMAL_PRIORITY_CLASS, win32process.HIGH_PRIORITY_CLASS, win32process.REALTIME_PRIORITY_CLASS] if pid == None: pid = win32api.GetCurrentProcessId() handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, True, pid) win32process.SetPriorityClass(handle, priorityclasses[priority])## end of http://code.activestate.com/recipes/496767/ def time_signal(): """" 時報を鳴らす """ for i in range(3): winsound.Beep(440,150) time.sleep(0.85) winsound.Beep(880,1400)if __name__ == '__main__': # 優先度を 4 : win32process.HIGH_PRIORITY_CLASS にセット setpriority(None, 4) # 1.5秒待って time.sleep(1.5) # 時報を鳴らす time_signal()ところが実際にやってみると、キーボードで入力していたり、Youtube を見ていたりしても、きれいに音がなってくれない。やっぱり性能が低い PC だと厳しい。Beep のハードウェア割り込みとタイマー割り込みで、そこに他の負荷がかかってダメなのかな。winsound.PlaySound(sound, flags) であらかじめ用意しておいた wave ファイルを鳴らした方が、気持ち悪くならないかな。NHKの時報音(もどき)をダウンロードして使ってみる(C で書かれた音を作るためのソースコードも入っている )。この音を、winsound.PlaySound("nhk.wav", winsound.SND_FILENAME)で鳴らすようにした。こっちの方がいいな。ちなみに、できるだけ正確な時間になにかをしようとしたら、sleep で何秒待って、何かをするというのは厳しいかもね。自前で時間を拾って、一定時刻を過ぎていたら何かするというようにしないと、同じ間隔で何かするというのが、負荷状況によっては、あまり正確にできない可能性がある。
2010.10.08
コメント(0)
wPython.org の Getting Started をサカナに第五弾 wxPython 入門(5) の続き。説明は前のエントリ。ここではソースコードと実行画面のみ。# -*- coding: utf-8 -*-import wxclass MyFrame(wx.Frame): """ メニューを作る """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(400,300)) self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE) # 個々のメニューオブジェクトを作成する # ファイルメニュー、編集メニュ、書式メニュー、表示メニュー、ヘルプメニューの各メニューオブジェクトを作成 file_menu= wx.Menu() edit_menu = wx.Menu() help_menu = wx.Menu() # 各メニュー毎にメニューアイテムを作っていく # ファイルメニュー menuNew = file_menu.Append(wx.ID_NEW, "新規作成 (&N)", "ファイルを新しく作ります") menuOpen = file_menu.Append(wx.ID_OPEN, "ファイル (&F)", "ファイルを開きます") menuSave = file_menu.Append(wx.ID_SAVE, "上書き保存 (&S)", "編集中のファイルに上書きで保存します") menuSaveas = file_menu.Append(wx.ID_SAVEAS, "名前を付けて保存 (&A)", "新しく名前をつけてで保存します") file_menu.AppendSeparator() # メニューセパレータ menuExit = file_menu.Append(wx.ID_EXIT, "終了 (&X)", "簡易エディタの終了します") # 編集メニュー menuUndo = edit_menu.Append(wx.ID_UNDO, "元に戻す (&U)", "編集を元に戻します") menuCut = edit_menu.Append(wx.ID_CUT, "切り取り (&T)", "選択箇所を切り取ります") menuCopy = edit_menu.Append(wx.ID_COPY, "コピー (&V)", "選択箇所をコピーします") menuPaste = edit_menu.Append(wx.ID_PASTE, "貼り付け (&P)","切り取られた箇所を貼り付けます") # ヘルプメニュー menuHelp = help_menu.Append(wx.ID_HELP, "ヘルプの表示 (&H)", "プログラムのヘルプを表示します") menuAbout = help_menu.Append(wx.ID_ABOUT, "バージョン情報 (&A)", "プログラムのヘルプを表示します") # メニューバーを作成し、個々のメニューをメニューバーに追加していく menuBar = wx.MenuBar() menuBar.Append(file_menu,"ファイル (&F)") menuBar.Append(edit_menu, "編集 (&E)") menuBar.Append(help_menu, "ヘルプ (&H)") # 個々のメニューアイテムを、イベントハンドラーにバインドする self.Bind(wx.EVT_MENU, self.OnNew, menuNew) self.Bind(wx.EVT_MENU, self.OnOpen, menuOpen) self.Bind(wx.EVT_MENU, self.OnSave, menuSave) self.Bind(wx.EVT_MENU, self.OnSaveas, menuSaveas) self.Bind(wx.EVT_MENU, self.OnExit, menuExit) self.Bind(wx.EVT_MENU, self.OnUndo, menuUndo) self.Bind(wx.EVT_MENU, self.OnCut, menuCut) self.Bind(wx.EVT_MENU, self.OnCopy, menuCopy) self.Bind(wx.EVT_MENU, self.OnPaste, menuPaste) self.Bind(wx.EVT_MENU, self.OnHelp, menuHelp) self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout) # メニューバーを Frame にセットする self.SetMenuBar(menuBar) # ステータスバーを作成する self.CreateStatusBar() # 表示 self.Show(True) # メニューが選択されたら、選択されたことを標準出力に表示する def OnNew(self, event): print "Select New" def OnOpen(self, event): print "Select Open" def OnSave(self, event): print "Select Save" def OnSaveas(self, event): print "Select Save As" def OnUndo(self, event): print "Select Undo" def OnCut(self, event): print "Select Cut" def OnCopy(self, event): print "Select Copy" def OnPaste(self, event): print "Select Paste" def OnHelp(self, event): print "Select Help" def OnAbout(self, event): print "Select About" def OnExit(self, event): print "Select Exit" app = wx.App(False)frame = MyFrame(None, '簡易エディタ')app.MainLoop()
2010.10.06
コメント(0)
wPython.org の Getting Started をサカナに第五弾。これまでテキストコントロール (wx.TextCtrl) に文字を表示し、文字色や背景色を変更したり、表示フォントを変更してみた。そして、メニューやステータスバーを付けるところまでやった。今度は、メニューを選択したときに何かの処理が行われるようなところを作ってみる。つまり、話題としては、イベントハンドリング(Event handling) の箇所。wxPython 入門 (1) フレームとアプリケーションwxPython 入門 (2) テキストコントロールwxPython 入門 (3)文字色、背景色とフォントwxPython 入門 (4) メニューとステータスバーそういえば、前回、Standard event identifiersで、wx.ID_xxx のドキュメントがあるのを気づかずに通り越していた。wxID_LOWEST = 4999、 wxID_HIGHEST = 5999 なので、この範囲はユーザーが直接使うのは避けましょうということも書いてあった。さらにメニューを作るときには、Stock items を見るとよさそう。メニューとイベントとイベントハンドラーを結びつけるまずは、下記を確認。メインループ(Main loop)とは、イベント駆動型GUIなどの機能を持つアプリケーションで典型的な設計手法。イベントループ(Event loop)とも呼ばれる。常に実行されているループを持ち、ユーザーイベントの有無をループする度に確認し、それイベントを処理する。何らかの方法でイベントを処理すると、制御は前述のループに戻り、次にイベントが発生するまでループを回り続ける。このようなプログラムではループが最上位の制御構造となっており、そのため「メイン」と名づけられている。メインループ (Wikipedia より)ということで、wxwxPython で作ったプログラムを実行するとき、一番最後に app.MainLoop() としているのは、プログラムがイベントループの状態にさせるため。そうすると、プログラムは、マウスやキーボード、あるいはタイマーなどのイベントを捕まえて、それによって何かのアクションが引き起こされるようになる。wxPython のイベントには、wxPython のイベントの一覧 のようなものがある。これは、import wxfor x in dir(wx): if x.startswith('EVT_'): print x のようにして参照することもできる。 たとえば、メニューを選択したときには、wx.EVT_MENUが発生する。これを拾って、何かの処理を起動してやるという処理を書く必要がある。このイベントと、そのイベントに対応する処理(イベントハンドラー) を結び付けてあげるのに Bind メソッドを使う。Bind の構文は、def Bind(self, event, handler, source=None, id=wxID_ANY, id2=wxID_ANY):例:self.Bind(wx.EVT_SIZE, self.OnSize)self.Bind(wx.EVT_BUTTON, self.OnButtonClick, theButton)self.Bind(wx.EVT_MENU, self.OnExit, id=wx.ID_EXIT)たとえば、次のようになる。 menuItem = filemenu.Append(wx.ID_ABOUT, "&About"," このプログラムの情報") self.Bind(wx.EVT_MENU, self.OnAbout, menuItem) Bind の第一引数は、イベントの種類。メニュー操作を扱うためのイベントなので wx.EVT_MENU が指定されている。次に指定されているのが、イベントハンドラー。このメソッドでメニューが選択されたときの処理メソッドを指定する(これは別途作成する)。3つめの引数がソースで、ここではメニューアイテムオブジェクト。ここで指定されたメニューアイテムが選択されると EVT_MENU のイベント発生し、イベントハンドラーの self.OnAbout に渡され、そこでなんらかの処理をする。なので、イベントハンドラーのメソッドには、このイベントを引数として受け取れるようにする必要があるので def foo(self, event) のようになる。前回のコードでは、filemenu.Append(wx.ID_ABOUT, "&About"," このプログラムの情報")としていたが、各メニューアイテムオブジェクト(ソース)を格納する変数を用意しなければならないので、menuItem = filemenu.Append(wx.ID_ABOUT, "&About"," このプログラムの情報")のようにするところに注意。そうしたうえで、バインドする。self.Bind(wx.EVT_MENU, self.OnAbout, menuItem)さらに、MyFlame クラスの中で、def OnAbout(self, event): # イベントを受け取って、何かを処理する print "Select About”のようになる。ちなみに、wx.EVT_MENU や wx.EVT_BUTTON などのイベントは、すべて wx.Event のサブクラス。また、あるメソッドがイベントを受け取ったときに処理をせずに、イベントループに戻すには、event.Skip() を呼び出せばよい。たとえば、def OnButtonClick(self, event): if (some_condition): do_something() else: event.Skip()のように使う。もし、ボタンがクリックされても、some_condition が False であれば、このメソッドでは処理を行わないことになる。もし、このスキップを行わない場合、メソッド終了とともに、このイベントの扱いは完了してしまう。けれども、event_skip() としておくと、他のメソッドでこのイベントを扱うように設定されてれば、引き続き、そのメソッドで処理ができる。ということで、とりあえず、各メニューが選択されたら、コンソール上に "Select 選択されたメニュー" を表示するようにしてみた。コードが少し長くなるので、次のエントリに続く。
2010.10.06
コメント(0)
wPython.org の Getting Started をサカナに第四弾。これまでテキストコントロール (wx.TextCtrl) に文字を表示し、文字色や背景色を変更したり、表示フォントを変更することをやってみた。wxPython 入門 (1) wxPython 入門 (2) wxPython 入門 (3)今日は、メニューをつけてみることにする。メニューバーを作るWindows のメモ帳と同じようなメニューを作ってみることにする。ただし、全部作ると面倒なので適宜省略する。メニューを作るには、まず、各々のメニューオブジェクト(wx.Menu) を作る。次に、各メニュー(ファイル、編集、書式...) を選択すると表示されるメニューアイテムを追加(Append)していく。各メニューの中で区切り線を入れたければ、Separator オブジェクトを挿入したい箇所に AppendSeparator で追加する。各メニューオブジェクトの設定が終わったら、メニューバー(wx.MenuBar) を作って、そこに各メニューを追加(Append)する。最後にメニューオブジェクトを、フレームにセットする(wx.SetMenuBar)。各メニューオブジェクト(ファイル,編集...) にメニューアイテムを追加するときには、メニューオブジェクト.Append( ID, メニュー表示, ステータスバーのメッセージ) の順に、たとえば、file_menu.Append(wx.ID_ANY, "新規作成 (&N)", "ファイルを新しく作ります") と指定する。Getting Started を見ると、ID に対して wx.ID_EXIT や wx.ID_ABOUT など、標準で用意されている ID を使っているが、標準以外の ID を使おうとすれば定義が必要になる(値は整数)。実際には、このIDはメニューアイテムのどれかを識別するためにユニークな整数が割り当てられていればよい。手作業で一つ一つ、ID_XXX = 1, ID_XXY = 2, ... と定義を入れていってもよいのだろうが、数が多くなると大変だし間違いが起こりやすくなる。Style Guide for wxPython code を読むと、"3. Don't use IDs. There is very rarely a good reason to use them." 特別な場合以外は、ID を独自に設定する意味はなさそうだし、むしろ下手につけない方がよいようなので、wx.ID_ANY を指定することにしようと思ったが、EXCEPTION: (there's always an exception!) Use standard IDs for standard menus, buttons, etc. It is useful to use the standard IDs because they may turn on standard functionality, such as menu item remapping for wxMac, automatic Dialog completion or cancellation, using stock button labels and images, etc. A list of these standard IDs can be found in the "Constants -- Stock items" section of the wxWidgets Reference manual. Example:item = FileMenu.Append(wx.ID_EXIT, "&Quit") This will put the Quit menu where it should be on OS-X, for instance.と、標準的な ID については、標準のものを使った方がよいかなぁ。ということで、標準の ID を使った。Mac OSX 以外でそういうメリットがあるか分からないけど。メニューアイテムの文字列については、&X のようにアンパサンドの後にある文字が、自動的にアクセラレーターキーになる。以下、コードが長くなると見づらくなるので、メニューに関連するところだけにしておく。# -*- coding: utf-8 -*-import wxclass MyFrame(wx.Frame): """ メニューを作る """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(400,300)) # 個々のメニューオブジェクトを作成する # ファイルメニュー、編集メニュ、書式メニュー、表示メニュー、ヘルプメニューの各メニューオブジェクトを作成 file_menu= wx.Menu() edit_menu = wx.Menu() format_menu = wx.Menu() view_menu = wx.Menu() help_menu = wx.Menu() # 各メニュー毎にメニューアイテムを作っていく # ファイルメニュー file_menu.Append(wx.ID_NEW, "新規作成 (&N)", "ファイルを新しく作ります") file_menu.Append(wx.ID_OPEN, "ファイル (&F)", "ファイルを開きます") file_menu.Append(wx.ID_SAVE, "上書き保存 (&S)", "編集中のファイルに上書きで保存します") file_menu.Append(wx.ID_SAVEAS, "名前を付けて保存 (&A)", "新しく名前をつけてで保存します") file_menu.AppendSeparator() # メニューセパレータ file_menu.Append(wx.ID_EXIT, "終了 (&X)", "簡易エディタの終了します") # 編集メニュー edit_menu.Append(wx.ID_UNDO, "元に戻す (&U)", "編集を元に戻します") edit_menu.Append(wx.ID_CUT, "切り取り (&T)", "選択箇所を切り取ります") edit_menu.Append(wx.ID_COPY, "コピー (&V)", "選択箇所をコピーします") edit_menu.Append(wx.ID_PASTE, "貼り付け (&P)","切り取られた箇所を貼り付けます") # ヘルプメニュー help_menu.Append(wx.ID_HELP, "ヘルプの表示 (&H)", "プログラムのヘルプを表示します") # メニューバーを作成する menuBar = wx.MenuBar() # 個々のメニューをメニューバーに追加していく menuBar.Append(file_menu,"ファイル (&F)") menuBar.Append(edit_menu, "編集 (&E)") menuBar.Append(format_menu, "書式 (&O)") menuBar.Append(view_menu, "表示 (&V)") menuBar.Append(help_menu, "ヘルプ (&H)") # メニューバーを Frame にセットする self.SetMenuBar(menuBar) # ステータスバーを作成する self.CreateStatusBar() # 表示 self.Show(True) app = wx.App(False)frame = MyFrame(None, '簡易エディタ')app.MainLoop()今回はメニューを作るところまでだが、メニューを作り終わったら、そのメニューが選択されたときに (メニュー選択のイベントが発生したときに、どのようなアクションをとるかということを結びつける(バインドする, BIND)。ここは次の回にやる予定。以下、標準で用意されている wx.ID_??? と、そこで定義されている値を見てみたもの。自分で ID を定義するときには、これとぶつからないように 10以下と 5000台の数は使わないようにすることにした。> import wx> for name in dir(wx):... if name.startswith("ID_"):... print name, eval("wx."+name)...ID_ABORT 5115ID_ABOUT 5014ID_ADD 5118ID_ANY -1ID_APPLY 5102ID_BACKWARD 5107ID_BOLD 5126ID_CANCEL 5101ID_CLEAR 5034ID_CLOSE 5001ID_CLOSE_ALL 5021ID_CONTEXT_HELP 5112ID_COPY 5032ID_CUT 5031ID_DEFAULT 5108ID_DELETE 5038ID_DOWN 5121ID_DUPLICATE 5036ID_EDIT 5030ID_EXIT 5006ID_FILE 5050ID_FILE1 5051ID_FILE2 5052ID_FILE3 5053ID_FILE4 5054ID_FILE5 5055ID_FILE6 5056ID_FILE7 5057ID_FILE8 5058ID_FILE9 5059ID_FIND 5035ID_FORWARD 5106ID_HELP 5009ID_HELP_COMMANDS 5018ID_HELP_CONTENTS 5015ID_HELP_CONTEXT 5020ID_HELP_INDEX 5016ID_HELP_PROCEDURES 5019ID_HELP_SEARCH 5017ID_HIGHEST 5999ID_HOME 5122ID_IGNORE 5117ID_INDENT 5133ID_INDEX 5125ID_ITALIC 5127ID_JUSTIFY_CENTER 5128ID_JUSTIFY_FILL 5129ID_JUSTIFY_LEFT 5131ID_JUSTIFY_RIGHT 5130ID_LOWEST 4999ID_MORE 5109ID_NEW 5002ID_NO 5104ID_NONE -3ID_NOTOALL 5114ID_OK 5100ID_OPEN 5000ID_PAGE_SETUP 5012ID_PASTE 5033ID_PREFERENCES 5022ID_PREVIEW 5013ID_PREVIEW_CLOSE 1ID_PREVIEW_FIRST 6ID_PREVIEW_GOTO 8ID_PREVIEW_LAST 7ID_PREVIEW_NEXT 2ID_PREVIEW_PREVIOUS 3ID_PREVIEW_PRINT 4ID_PREVIEW_ZOOM 5ID_PRINT 5010ID_PRINT_SETUP 5011ID_PROPERTIES 5041ID_REDO 5008ID_REFRESH 5123ID_REMOVE 5119ID_REPLACE 5039ID_REPLACE_ALL 5040ID_RESET 5111ID_RETRY 5116ID_REVERT 5005ID_REVERT_TO_SAVED 5140ID_SAVE 5003ID_SAVEAS 5004ID_SELECTALL 5037ID_SEPARATOR -2ID_SETUP 5110ID_STATIC 5105ID_STOP 5124ID_UNDELETE 5139ID_UNDERLINE 5132ID_UNDO 5007ID_UNINDENT 5134ID_UP 5120ID_VIEW_DETAILS 5042ID_VIEW_LARGEICONS 5043ID_VIEW_LIST 5045ID_VIEW_SMALLICONS 5044ID_VIEW_SORTDATE 5046ID_VIEW_SORTNAME 5047ID_VIEW_SORTSIZE 5048ID_VIEW_SORTTYPE 5049ID_YES 5103ID_YESTOALL 5113ID_ZOOM_100 5135ID_ZOOM_FIT 5136ID_ZOOM_IN 5137ID_ZOOM_OUT 5138
2010.10.02
コメント(2)
wxPython 入門 (1) 、wxPython 入門 (2) に引き続き、wPython.org の Getting Started をサカナに第三弾。"Building a simple text editor" のあたりを見ていく。シンプルなテキストエディタを作ってみましょうというところ。TextCtrl の style を指定すれば、スクロールやワードラップ、右寄せ、左寄せ、センタリング等々の設定ができるところまで wxPython 入門 (2) で確認したが、文字の色をつけたり、フォントを指定したりするにはどうしたらよいかということを見ていく。要するに、TextCtrl をもう少し見ていきましょうということ。TextCtrl の文字色と背景色を変えるテキストコントロールの SetForgroundColour メソッドで文字色、SetBackgroundColour メソッドで背景色を変更することができる。文字色は、英語名でも、16進形式でも、10進形式(RGB を 0-255で指定) でも可能だが、英語名の場合は、すべての名前が使えるわけではなく、red, blue, yellow, black, white, gray... といった基本色以外は使えない。名前は何が使えるか、未調査。たとえば、wheet みたいなものは使えない。wx.WHITE、wx.GREEN、wx.BLACK、wx.CYAN, wx.RED, wx.LIGHT_GREY のようなものも使える。無効な色が指定された場合は、デフォルトの色になる。10進形式の場合は、wxColour(R, G, B) で指定する(それぞれ 0~255)。ちなみに、"colour" であって、"color" でないので注意(英国式の綴り)、と思ったら、実は、wx.Color(R,G,B) でも大丈夫だった。どちらかに統一しておいたほうがよいだろう。wx.LIGHT_GREY はあるが、wx.LIGHT_GRAY はないなど、基本的には英国式綴りをベースにした方が問題ないように思える(最初は英国綴りだけしかなくて、みな間違えるので米国式綴りも定義されたんじゃなかろうか。それゆえ、すべてのクラスで両方あるわけではないと。歴史的経緯については調べていないけど)# -*- coding: utf-8 -*-import wxclass MyFrame(wx.Frame): """ 文字色と背景色を変える """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(400,300)) self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE) # 文字色の指定 # 次の4つはどれでも同じ結果になる。 # self.control.SetForegroundColour("red") # self.control.SetForegroundColour(wx.RED) # self.control.SetForegroundColour(wx.Colour(255, 0, 0)) self.control.SetForegroundColour("#ff0000") # 背景色の指定 self.control.SetBackgroundColour("#e0ffff") # 表示 self.Show(True) app = wx.App(False)frame = MyFrame(None, '簡易エディタ')app.MainLoop()wx.色 で定義されているのは、次の色。wx.BLACKwx.WHITEwx.REDwx.BLUEwx.GREENwx.CYANwx.LIGHT_GREYTextCtrl のフォントを変える今度は、フォントの種類を変えたり、文字の大きさを変えたり、イタリックにしたり、太字にしたりしてみる。指定は、SetFont メソッドを使う。ただし、直接値を渡すのではなく、wx.Font() でフォント指定のオブジェクトを作ってから渡す。その際には、フォントのサイズ、ファミリー、スタイル、ウェイトを指定しなければならない。下線を文字の下につけたいときは、引数の最後に True を追加する (1でもよい)。False なら下線なし。フォントファミリーは、wx.FONTFAMILY_DEFAULT デフォルトwx.FONTFAMILY_DECORATIVE デコラティブwx.FONTFAMILY_ROMAN ローマン(serif) wx.FONTFAMILY_SCRIPT ハンドライティング(手書き風)wx.FONTFAMILY_SWISS スイス(sans-serif) フォントwx.FONTFAMILY_MODERN 固定ピッチフォントwx.FONTFAMILY_TELETYPE テレタイプフォントフォントスタイル (FONTSTYLE_) は、wx.FONTSTYLE_NORMAL ノーマルwx.FONTSTYLE_SLANT スラントwx.FONTWEIGHT_BOLD ボールドwx.FONTWEIGHT_LIGHT ライトフォントウェイトは、wx.FONTWEIGHT_NORMAL ノーマルwx.FONTWEIGHT_LIGHT ライトwx.FONTWEIGHT_BOLD ボールドただし、wx.DEFAULT, wx.NORMAL, wx.SWISS, wx.BOLD のように、前半の FONTFAMILY_ や FONTSTYLE_ をつけなくても、実際の定数の INT の数値が同じなので問題ないようだ。同じ定数が定義されている。検索してみると、両方見つかるが、デモなど見ても、wx.DEFAULT のように短縮した形式になっているので、短い形式で指定することにした。次の例では、24ポイントのノーマルフォントで太字でイタリックで表示している。# -*- coding: utf-8 -*-import wxclass MyFrame(wx.Frame): """ 文字色と背景色とフォントを変える """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(400,300)) self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE) # 文字色の指定 self.control.SetForegroundColour("#ff0000") # 背景色の指定 self.control.SetBackgroundColour("#e0ffff") # フォントの指定 font = wx.Font(24, wx.NORMAL, # wx.FONTFAMILY_DEFAULT wx.ITALIC, # wx.FONTSTYLE_ITALIC wx.BOLD) # wx.FONTWEIGHT_BOLD self.control.SetFont(font) # 表示 self.Show(True) app = wx.App(False)frame = MyFrame(None, '簡易エディタ')app.MainLoop()TextCtrl のフォント名を指定する使用するフォントを名前で指定することもできる。その場合、wx.Font(ポイント, ファミリー, スタイル, ウェイト , アンダーライン(T|F), フォント名) のような指定になる。アンダーラインのところで True を指定すれば、文字に下線が引かれる。False なら通常の表示。次の例は、フォントにメイリオを使って、下線を表示している例。# -*- coding: utf-8 -*-import wxclass MyFrame(wx.Frame): """ 文字色と背景色、フォントなどを変える """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(400,300)) self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE) # 文字色の指定 self.control.SetForegroundColour("#ff0000") # 背景色の指定 self.control.SetBackgroundColour("#e0ffff") # フォントの指定 font = wx.Font(32, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False, "メイリオ") self.control.SetFont(font) # 表示 self.Show(True) app = wx.App(False)frame = MyFrame(None, '簡易エディタ')app.MainLoop()ちなみに、TexCtrl を駆使すれば、それなりのリッチテキストエディタが作れるはずだが、リッチテキストエディタがほんとうに作りたければ、むしろ、wx.RichTextCtrl を使った方がいいだろう。デモを見ると、こういうものがある。ただし、ちゃんとしたアプリケーションとしては仕上げられてはいないから、表示するところまでで、保存はテキスト形式になっちゃうけど。TextCtrl 自体、まだまだネタはあるのだが、おいおい取り込むことにして、とりあえず、先に進むことにする。
2010.10.01
コメント(0)
全214件 (214件中 1-50件目)