‘Python’ カテゴリーのアーカイブ

GAE/PythonでWTFormsのDateTimeLocalFieldを使う

HTML5の<input type=”datetime-local”>を使うとローカル時間での日付時刻入力フィールドを作成できます。

WTFormsでこれを使用するにはDateTimeLocalFieldを使えばいいのですが、バリデーションが通らなくて困っていました。
結論としては、フォーマットを指定すれば良いようです。

from wtforms.fields.html5 import DateTimeLocalField

class SampleForm(BaseForm):
    start_at = DateTimeLocalField(u'開始日時*',
        [validators.required()], format='%Y-%m-%dT%H:%M')

PythonでMIDI出力をしてみる

既存のPythonで作ったWindowsアプリケーションにMIDI出力を組み込む用事があったので、実験してみました。

参考サイトはこちら。

sulume blog» ブログアーカイブ » python で MIDI を使う

MIDIIO.dllというのはおーぷんMIDIぷろじぇくとで公開されているMIDIメッセージ入出力用ライブラリです。

これもダウンロードして、pyファイルと同じ場所に置いておきます。

で、ソースコードはこちら。

import ctypes
import time

midiiolib = ctypes.windll.LoadLibrary(r".\MIDIIO.dll")

c_deviceName = ctypes.create_string_buffer(32)

midiiolib.MIDIOut_GetDeviceName(0, c_deviceName, 32)
midiout = midiiolib.MIDIOut_Open(c_deviceName.value)

c_mess = ctypes.create_string_buffer(3)
c_mess.value = '\x90\x3C\x64'

midiiolib.MIDIOut_PutMIDIMessage(midiout, c_mess.value, 3)

time.sleep(3)

midiiolib.MIDIOut_Close(midiout)

説明することもあまりないですが、8行目のMIDIOut_GetDeviceNameで、MIDI出力の先頭のデバイスの名前を先に取得します。

で、その名前を使ってMIDIOut_Openで出力デバイスを開きます。

11~12行目ではノートを作成します。とりあえずドの音でも鳴らしておきます。この辺もMIDIIO.dllに入っていたドキュメントのサンプルと同じ。

あとはMIDIOut_PutMIDIMessageで出力するだけです。

ちゃんと閉じておかないと、次回音が鳴らなかったりする(オープンに失敗します)ので、MIDIOut_Closeで閉じておきましょう。

実験として、ちょっと長いデータを指定してみる。

import ctypes
import time

midiiolib = ctypes.windll.LoadLibrary(r".\MIDIIO.dll")

c_deviceName = ctypes.create_string_buffer(32)

midiiolib.MIDIOut_GetDeviceName(0, c_deviceName, 32)
midiout = midiiolib.MIDIOut_Open(c_deviceName.value)

notes = ['\x90\x3C\x64',
         '\x90\x3E\x64',
         '\x90\x40\x64',
         '\x90\x41\x64',
         '\x90\x43\x64',
         '\x90\x45\x64',
         '\x90\x47\x64',
         '\x90\x48\x64']

c_mess = ctypes.create_string_buffer(3)

for note in notes:
    c_mess.value = note

    midiiolib.MIDIOut_PutMIDIMessage(midiout, c_mess.value, 3)
    time.sleep(0.5)

time.sleep(1.0)

midiiolib.MIDIOut_Close(midiout)

和音を鳴らしてみるテスト。

import ctypes
import time

midiiolib = ctypes.windll.LoadLibrary(r".\MIDIIO.dll")

c_deviceName = ctypes.create_string_buffer(32)

midiiolib.MIDIOut_GetDeviceName(0, c_deviceName, 32)
midiout = midiiolib.MIDIOut_Open(c_deviceName.value)

notes = ['\x90\x3C\x64',
         '\x90\x40\x64',
         '\x90\x43\x64']

c_mess = ctypes.create_string_buffer(3)

for note in notes:
    c_mess.value = note

    midiiolib.MIDIOut_PutMIDIMessage(midiout, c_mess.value, 3)

time.sleep(3.0)

midiiolib.MIDIOut_Close(midiout)

とりあえずこれだけできれば満足なので終了。


ImportError: MemoryLoadLibraryの対処法

wxPythonで作ったWin32アプリケーションをpy2exeでひとつのファイルにまとめていたら、あるPCで以下のようなエラーが発生。

  File "zipextimporter.pyo", line 82, in load_module

  File "wx__init__.pyo", line 45, in <module>

  File "zipextimporter.pyo", line 82, in load_module

  File "wx_core.pyo", line 4, in <module>

  File "zipextimporter.pyo", line 98, in load_module

ImportError: MemoryLoadLibrary failed loading wx_core_.pyd

発生したマシンはWindows XP Professional SP3で、ユーザは管理権限。他のマシンでは発生しなくて、発生原因が不明だったのだけど、「ImportError: MemoryLoadLibrary failed loading wx_core_.pyd」で検索したらそれっぽいのがたくさん…

結構メジャーな問題?

解決策は主にこのフォーラムに。

OpenSubtitles.org // View topic – Solution for MemoryLoadLibrary failed loading wx_core_.pyd

早い話が、msvcp71.dllを持ってきて入れろってことらしい。py2exeを実行したときに一緒に配置されるmsvcr71.dllではなく。

msvcp71.dllが何なのかと、うまく動かない環境ではこのファイルがどうなってるのかは後で調べます。軽く見たところでは、こんなことらしい。

答えてねっと 投稿全文表示

下記のVC++2005再頒布可能パッケージに含まれているのかな…未確認。

ダウンロードの詳細 : Visual C++ 2005 再頒布可能パッケージ (x86)

出所不明だけど、DLLだけ入手するなら以下のサイトから。

DLL-files.com – Download of msvcp71

同じ人の別のマシンで、また別のエラーが出てるらしいんだよなぁ…それも調べないと。

追記:

ProblemsToBeFixed – py2exe.org

ってゆーか、公式にまるっと全部書いてあったYo!

py2exe 0.6.8で発生したので、とりあえず0.6.9にしてみるか…0.6.8で直ってるみたいなことが書いてあるのだけど…

まぁでも解決策はmsvcp71.dllを置けってことなのね。



LeopardでHIDを使おうとした失敗のメモ

Mac OSX 10.5.6 Leopard+Python 2.5でHIDを使おうとしばらく頑張ってたけど、とりあえず失敗の歴史メモ。解決方法は書いていません。

PyUSB

libusbのラッパー。これが動けば一番楽なのだけど…

libusbはkernalにHIDを取られてしまうのでOSXで動かないとどこかに書いてあった。一応.kextファイルを作成することで動くようになるらしいのだけど、今回rootでの処理が必要なものは使えなかったので諦め。

ちなみに良質なコードのサンプルはpyMissileにある。

これも。日本語。Python/PyUSB – SasadaLabWiki

あと、便利なドキュメントはこちら。wiki:projects:python:pyusb:pydoc    [wiki.erazor-zone.de]

それとlibusb用の.kextファイルの作り方はこちら。

Re: device not opened for exclusive access?: msg#00058 lib.libusb.devel.general

ちなみに何が失敗するかというと、こんな感じ。

>>> import usb
>>> bus = usb.busses()
>>> dev = bus[4].devices[1]
>>> handle = dev.open()
>>> handle.detachKernelDriver(0)
>>> handle.detachKernelDriver(1)
>>> conf = dev.configurations[0]
>>> handle.setConfiguration(conf)
>>> intf = conf.interfaces[0][0]
>>> intf
<usb.Interface object at 0x11398>
>>> handle.claimInterface(intf)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
usb.USBError: usb_claim_interface: couldn't claim interface
>>> handle.setAltInterface(intf)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
usb.USBError: usb_set_altinterface: could not set alternate interface

SWIG+HID_Utilities

Control USBIO module from Python on MacOSX

基本的には、上記サイトに書いてある通り。

はまった場所はHID_Utilities_External.hのvoid *をchar *に書き換えておかないといけないこと。これはdylibをビルドしたあとならHID_Utilities_External.hの修正だけでOK。ビルド前なら一緒にHID_Queue_Utilities.cの当該部分も変更しておく必要あり。あとキャスト必要かも。

SetReportは成功して、デバイスにコマンドを処理させることはできた。

ただ、SWIGにはコールバックでPythonのメソッドを呼ばせる方法がないらしく頓挫。まぁ、なくても変数には入るらしくて、それを監視すればいいだけの話なのだけれど、それがうまくいかなくて結局頓挫。一応その方法の説明は以下のあたり。%constantディレクティブを使えばいいらしい。

SWIG Basics Pointers to functions and callbacks

Users guide for fd2python ←コールバックあるような気も?

もうひとつ頓挫の理由として、HIDGetReportの結果が目的の結果にならないこと。データを読み出すコマンドをHIDSetReportで送った後には、確かに値が変化するのだけど、どうも正しいデータにならない…原因つかめず。あと、iSerialNumberの取得もデータが化けてうまくいかず。

pyglet

pyglet自体はマルチメディア関連のクロスプラットフォームフレームワークみたいなもの。

その中にdarwin_hid.pyというOSX用のHIDライブラリがある。

これはcocoaにctypesでアクセスしている模様。これが一番確率高いなー、とは思う。

実際、

import pyglet.input
devices = pyglet.input.get_devices()
dev = devices[1]

だけでHIDの一覧を取得可能。しかしこのデバイスにSetReportをしたいのだけどどうすればいいのか不明。元々キーボードやマウスやコントローラーに特化しているようで、深いことをしようとしたら自分で書く必要があるっぽい。まだ追いかける余地は結構あるけどなー…


Python対話モードでのコード補完

Pythonの対話モードでコード補完を使えるということを知った。

環境はMac OSX Leopard+Python2.5.4(Ports)

インタラクティブモードで補完とかヒストリの読み書きとか – Seeking for my unique color.

readlineモジュールがインストールされていなかったので、Portsでインストール。

$ sudo port install py25-readline

これで

>>> import rlcompleter, readline
>>> readline.parse_and_bind("tab: complete")

で補完がばっちり効く。これは便利。

毎回打ち込むのは忘れそうなので、インタラクティブシェルが起動したときに自動で実行されるようにしたい。どうやらsitecustomize.pyというものを書けばいいらしい。

$ vi /Library/Python/2.5/site-packages/sitecustomize.py

import rlcompleter, readline
readline.parse_and_bind("tab: complete")

でいいかなと思ったらどうやら違うらしい。sitecustomize.pyはどこに置けばいいんだろう…


Pythonを使ってUSBデバイスの接続検知をする

というのを色々調べてMSDN見て構造体の定義を書いたりして、RegisterDeviceNotificationを使ってwxPythonのトップウィンドウにWM_DEVICECHANGEを送るところまで成功して、それをSpy++で確認中にOSが落ちたり色々あったけど、じゃあそれをWndProcで処理する方法を調べようかなと思って「WM_DEVICECHANGE Python」で検索をかけたところ、カナダのサイトに行きついた末、そこからのリンクでwxPythonのwikiに”そのものずばり”なサンプルコードが載っていることを発見してやるせなくなったところが、今です。

前置き長すぎたけど、やり方はこちら。

MonitoringWindowsUsb – wxPyWiki

あー。

あー…。


PyUSBがVistaで使えないという話。

libusbをWindows Vistaに入れるとUSB機器全般使えなくなるらしい。

Pythonで開発中のUSBデバイスの操作に、PyUSB使おうと思っていただけに非常に残念。しかもlibusb-win32のこの更新頻度では対応の見込みは厳しそうだなぁ…

PyUSBがVistaではhid.dllを使うようになってくれたりしたらいいのかも。

調べてる最中に見つけた面白そうなものをメモ。

八角研究所 : レゴマインドストームNXTをPythonから操作するNXT_Pythonを使ってみる(1) – とりあえず走らせてみよう

独学Linux:WiiリモコンでBerylを動かす方法《実践編No.1》 – livedoor Blog(ブログ)

しかしPythonのライブラリの豊富さは何なの?

[追記]

libusb-win32のバックエンドにWinUSBを使う開発が進行中らしい。

LibUsb-Win32 – osdev-j (MMA) 

SourceForge.net: libusb-win32-devel

ちゃんと進行してるっぽい。2009年くらいのリリースとか。

でも自分の用途には間に合わないけどね!


Visual Studio 2005でIronPython

IronPythonで.NETでMONOでWindowsもMacOSXもまとめてヒャッハーしたくなったのでとりあえず導入してみた。

こちらのサイトがわかりやすい。
もう何時でもリリース出来るのでは? IronPython for Visual Studio 2005の9月版 – ふにゃるん

導入した時点のバージョンは「Visual Studio 2005 SDK Version 4.0」

ダウンロードはこちらから。
Download details: Visual Studio 2005 SDK Version 4.0

2007年2月版だったけど、インストール作業自体は上記と何も変わらず。

さっくり動いて超便利。

ところで、IronPythonって2.4系なのかー。

[追記]
と思ったらIronPython2.0のStableが4日前に来てたー!

http://www.codeplex.com/IronPython/Release/ProjectReleases.aspx?ReleaseId=8365

こっちは2.5 compatibleでっす。

あぁ…VS2008を買おうか迷う。


Pythonで、サーバからの画像取得で止まる

サーバで画像に動的にExif情報を付加して、それをローカルのPythonで大量取得しようとしてハマったのでメモ。

ローカル側は超省略するけど、以下のような感じ。

# URLをXMLから取得
image_path = i.find("Url").text
# 認証のかかっている場所から画像取得
img = urllib2.urlopen(urllib2.Request(unicode(image_path), None, {"Authorization": "Basic " + basicAuth}))
localfile = file('./' + id + ".jpg", "wb")
# 読み書き
localfile.write(img.read())
img.close()
localfile.close()

上記を10000ファイルくらい繰り返しで取得する。

が。

img.read()のところでなぜか止まる。

大体10個くらい読み込んだ時点で止まる。

Traceback (most recent call last):
  File "***.py", line 62, in <module>
    localfile.write(img.read())
  File "C:Python25libsocket.py", line 291, in read
    data = self._sock.recv(recv_size)
  File "C:Python25libhttplib.py", line 509, in read
    return self._read_chunked(amt)
  File "C:Python25libhttplib.py", line 573, in _read_chunked
    line = self.fp.readline()
  File "C:Python25libsocket.py", line 331, in readline
    data = recv(1)
KeyboardInterrupt

色々調べた結果、サーバ側でContent-Lengthを返さないと止まることがあるっぽい。

ということでサーバ側をちょこちょこ修正。

無事、止まらずに実行できるようになりました。