61 件 見つかりました。

CHALOW Search - hiChangeLog ChangeLog INDEX

[ 前へ ] 1 2 3 4 5 6 7 [ 次へ ]

SimpleHTTPRequestHandlerによるHTTPサーバの応答がsocket.getfqdnのせいで遅かった [python]

Windowsマシンで構成されたプライベートLANでpythonによるHTTPサーバを使おうとし、自PCからのアクセスには全く問題無かったが、他PCからの応答に対し5秒程度の遅延がある、という状況に出くわした。取得データに問題はなかったが、5秒もの長い間待つのは不便極まりないので、原因を調べた。

原因はSimpleHTTPRequestHandler.address_string中のsocket.getfqdnで、こいつの実行に5秒近くかかっていた。ここではログに記録するためのホスト名を取得しようとしている。アクセス元Windowsの「コンピュータ名」が結局記録されていたが、そんなもんは私の用途では全く重要ではない。なのでSimpleHTTPRequestHandlerを継承したクラスで以下のようにオーバーライドすることで解決した(IPアドレスだけ記録する)。

def address_string(self):
    host, port = self.client_address[:2]
    #return socket.getfqdn(host) # original
    return host

勿論、空文字だけを返してもOKだと思う。

ipythonの起動時のディレクトリを指定する [python]

バッチファイルを用意するのが簡単。

@echo off
cd %1
ipython
これをipythonstartup.batとかにしておいて下記でOK。
ipythonstartup (ディレクトリ)
参考(参考ってほどでもないけれど) http://lists.ipython.scipy.org/pipermail/ipython-user/2007-October/004744.html

実行している自分自身のスクリプトの絶対パスを知る [python]

print os.path.abspath(os.path.dirname(__file__))
ref. 134:実行しているスクリプトのパスを求める

matplotlibがpythonのグラフ作成ツールとして良さそうだ [python]

pythonでグラフを作成したい時、matplotlibが強力で便利そうだ。
windowsのインストーラでインストールした後に、以下を実行したらそれっぽいのが出てきた。

import pylab
x = range(0,10)
y = range(10,20)
pylab.plot(x,y)
pylab.savefig('C:\\temp\\hoge.png')
とても良さそうだ。

実体参照を通常の文字に変換する [python][正規表現]

HTMLなどでは

ü
などの実体参照でヘンテコめな文字を表現する場合がある。これを機械的に通常文字に変換したい。

そのものズバリの解説ページがあった。文字参照や実体参照を通常の文字に戻す [Python, Tips] - Programming Magic
以下で変換できているみたい。
import htmlentitydefs
g = lambda match: unichr(htmlentitydefs.name2codepoint[match.group(1)])
mystring = re.sub(u'&(.+?);', g, mystring)

IPythonコンソール、つまりはreadlineでキーバインド変更(ctrl-Hをバックスペースにしたい) [python]

IPython色分け、補完などでインタラクティブコンソールを何かと便利にするもの。併せて使用したいのが(py)readlineなるパッケージで、これは大雑把にはctrl-f,b,a,e,d,kといったemacs系のキーバインドなどを使えるようにするもの。

Windows XP SP2で ipython-0.8.4-py2.5.eggpyreadline-1.5.dev_r2876-py2.5.eggをeasy_installで導入してみた。便利。個人的にはキーバインドが気に入った。生コマンドプロンプトの時よりもかなり入力の効率は上がるだろう。だが、ctrl-Hはバックスペースになっていなかった。以下はこれを実現した際のメモ。

上述の通り、キーバインドはreadlineが担う。C:\Python25\Lib\site-packages\pyreadline-1.5.dev_r2876-py2.5.egg\pyreadline\modes\emacs.py を見てみると、538行目の init_editing_mode メソッドにて

self._bind_key('Control-b', self.backward_char)
などの記述を大量に発見。ここがキーバインドのキモだろう。カスタマイズの際は何か別に設定ファイル等を作るべきかもしれないが、ここは安直に大元を改造する方針でゆく。
改造も安直に下記1行の追加で大丈夫と思ったが、うまくいかなかった。(文字は消えるがカーソルは進む。制御文字との対応がうまくいってないとか何とかか?)
self._bind_key('Control-h', self.backward_delete_char)
でも以下は期待通りの動作(ctrl-Xでバックスペース)を実現した。
self._bind_key('Control-x', self.backward_delete_char)
生コマンドプロンプトはctrl-Hを解釈してバックスペースにしてくれるが、これがpyreadline側のctrl-H設定と干渉を起こしておかしな事になっているのかもしれない。

そこで、違うreadlineパッケージを試してみた。UNC Python Toolsなるものにreadlineが含まれる。上記pyreadlineをアンインストールした後にこれの1.12をインストールしてみた。C:\Python25\Lib\site-packages\readline\PyReadline.py の 1003行目に emacs_editing_mode メソッドがあって、上記 init_editing_mode と同様な記述が羅列されている。ここで下記1行を加えたら、ctrl-Hがバックスペースになった!
self._bind_key('Control-h', self.backward_delete_char)


できなかった理由、できた理由は全く理解していないが、ともかくもこれで結構快適な環境になりそうだ。

('09 11/16 追記) はるかに洗練された解決方法を発見した。IPythonを使ってZope3デバッグ :: 幕の内 - CMS - コンテンツマネジメントシステム

pythonからSendInput [Windowsプログラミング][python][PyWin32]

下記は、windowsのAPIのSendInputをpythonから呼ぶ例。
Adobe Readerに右矢印入力を10発送りこむ(開いてるPDFを10ページ進める)。エラー処理は省略。
この手のことはAutoHotKeyが専門だけど、pythonでできるにこしたことはない。
AppendKeyInput で win32con.KEYEVENTF_KEYUP を入れないと、同じキーの連続入力が出来ない。
http://mail.python.org/pipermail/python-win32/2005-April/003131.html を参照。

from ctypes import *
import win32ui, win32con

PUL = POINTER(c_ulong)
class KeyBdInput(Structure):
    _fields_ = [("wVk", c_ushort),
                ("wScan", c_ushort),
                ("dwFlags", c_ulong),
                ("time", c_ulong),
                ("dwExtraInfo", PUL)]

class HardwareInput(Structure):
    _fields_ = [("uMsg", c_ulong),
                ("wParamL", c_short),
                ("wParamH", c_ushort)]

class MouseInput(Structure):
    _fields_ = [("dx", c_long),
                ("dy", c_long),
                ("mouseData", c_ulong),
                ("dwFlags", c_ulong),
                ("time",c_ulong),
                ("dwExtraInfo", PUL)]
               
class Input_I(Union):
    _fields_ = [("ki", KeyBdInput),
                 ("mi", MouseInput),
                 ("hi", HardwareInput)]

class Input(Structure):
    _fields_ = [("type", c_ulong),
                ("ii", Input_I)]


def AppendKeyInput(vk):
    ret = []
    extra = c_ulong(0)
    ii_ = Input_I()
    scan = windll.user32.MapVirtualKeyA(vk, 0)
    ii_.ki = KeyBdInput(vk, scan, 0, 0, pointer(extra) )
    ret.append( ( win32con.INPUT_KEYBOARD, ii_ ) )

    ii2_ = Input_I()
    scan = windll.user32.MapVirtualKeyA(vk, 0)
    ii2_.ki = KeyBdInput(vk, scan, win32con.KEYEVENTF_KEYUP, 0, pointer(extra) )
    ret.append( ( win32con.INPUT_KEYBOARD, ii2_ ) )
    return ret

def ExecSendInput(inputs):
    num = len(inputs)
    FInputs = Input * num
    x = FInputs(*inputs)
    windll.user32.SendInput(num, pointer(x), sizeof(x[0]))
    

if __name__ == '__main__':
    inputs = []
    for i in range(10):
        inputs += AppendKeyInput(win32con.VK_RIGHT)
    
    acrobat = win32ui.FindWindowEx(None, None, 'AdobeAcrobat', None)
    acrobat.SetForegroundWindow()
    ExecSendInput(inputs)

pywin32でビットマップを扱う際のメモ [python][PyWin32]

なんちゃってwin32api(あるいはMFC)環境であるpywin32でビットマップを扱う際、意外と手間取ったのでメモ。

やりたかったことは、キャプチャしたビデオ信号のリアルタイム表示。つまり頻繁にやってくるビットマップのデータ列を頻繁に描画したいという状況。Windowsでのビットマップの描画方法は、私の理解では、多分、(有効な)ビットマップハンドルの取得方法に帰着する。なのでデータ列からビットマップハンドルを如何に作るかがここでのお題となる。今のところ、ctypesでCreateDIBSectionを呼出すのが良いと思っており、実際問題なく動作している。

win32gui.LoadImage や PyCBitmap.LoadBitmapFile は単純で簡単だが、リアルタイム表示においていちいちファイルを介するのは速度的に論外。StringIOでメモリ上にファイルオブジェクトを作成すれば速度の問題は解決するかと思い PyCBitmap.LoadBitmapFile でやってみたが、しばらくすると「このコマンドを実行する記憶域がありません」と例外が飛んでくるので、この方法も無理。

そもそもこんな状況ではwin32apiのCreateDIBSectionの使用が定石のひとつと思うが、残念なことにpywin32にこれは定義されていない。(Windows のデバイスコンテキストをビットマップファイルに変換する。Python でも参照)なのでctypesを介してこれを呼出すことにした。

とはいえ私はctypesの動作を深く理解していない(なので下記にいちいちメモをする)。そこでpygletのソースから該当部分を拝借する方法をとった。

CreateDIBSectionにはBITMAPINFOHEADERを渡す必要がある。これを定義するには如何のようにする(window/win32/types.py より)。

from ctypes import *
from ctypes.wintypes import *
class BITMAPINFOHEADER(Structure):
    _fields_ = [
        ('biSize', DWORD),
        ('biWidth', LONG),
        ('biHeight', LONG),
        ('biPlanes', WORD),
        ('biBitCount', WORD),
        ('biCompression', DWORD),
        ('biSizeImage', DWORD),
        ('biXPelsPerMeter', LONG),
        ('biYPelsPerMeter', LONG),
        ('biClrUsed', DWORD),
        ('biClrImportant', DWORD),
    ]

実際の値は下記のように作る(window/win32/__init__.py, Win32Window.get_icon より)。勿論、ヘッダの内容はデータ列の内容に依存する。DirectShowを使うなら AM_MEDIA_TYPE 内の VIDEOINFOHEADER 内に BITMAPINFOHEADER そのものがあるので、それをそのまま使えばよい。
def GetBitmapInfoHeader(w, h):
        header = BITMAPINFOHEADER()
        header.biSize = sizeof(header)
        header.biWidth = w
        header.biHeight = h
        header.biPlanes = 1
        header.biBitCount = 24
        header.biCompression = 0
        header.biSizeImage = w*h*3
        header.biXPelsPerMeter = 0
        header.biYPelsPerMeter = 0
        header.biClrUsed = 0
        header.biClrImportant = 0
        return header

そして以下のようにCreateDIBSectionを呼ぶ。(上と同じく__init__.pyより)
dataptr = c_void_p()
bitmap = windll.gdi32.CreateDIBSection(self.GetDC().GetHandleOutput(),
                                            byref(GetBitmapInfoHeader(w, h)),
                                            win32con.DIB_RGB_COLORS, byref(dataptr), None, 0)

あとはメモリデバイスコンテキストにbitmapをSelectObjectすれば準備完了。実際のデータを流すには下記のようにする。type(buf)はstr。(VideoCaptureモジュールのgetBufferより取得)
memmove(dataptr, buf, len(buf))

以上で問題なく動いている模様。

ctypesは以下に記述があった。
ctypesによるDLL内の関数の呼び出し
mtamaki.com : #47 (pythonからctypesで任意のDLLの関数を使う。)
2007年 11月 (1)。

描画(GDI、デバイスコンテキスト)にまつわるメモ [python][PyWin32]

GDIオブジェクト、デバイスコンテキスト、メモリデバイスコンテキストといった単語は作業中はなんとなく解ったつもりでいるが、少し間をおくと木端微塵に忘れる。pywin32で描画のコードを書こうとしたが、やっぱりすっかり忘れていて参った。動いたコードをメモしておく。

from pywin.mfc import dialog
import win32con, win32ui

class Mydialog(dialog.Dialog):

    dlgstyle = (win32con.WS_DLGFRAME | win32con.DS_MODALFRAME | win32con.WS_POPUP |
                win32con.WS_VISIBLE |  win32con.WS_CAPTION  | win32con.WS_SYSMENU )
    tmpl = [ ["my dialog", (0, 0, 200, 100), dlgstyle], ]
    def __init__(self): dialog.Dialog.__init__(self, self.tmpl)

    def OnPaint(self):
        dc = self.GetDC()

        # copy itself
        dc.BitBlt((0,0), (20,20), self.GetWindowDC(), (0,0), win32con.SRCCOPY)

        # line
        dc.LineTo((30,30))

        # line with a customized pen
        cpen = win32ui.CreatePen(win32con.PS_SOLID, 5, 10000000)
        dc.SelectObject(cpen)
        dc.LineTo((50,50))

        # drawing on memory device context
        dcmem = dc.CreateCompatibleDC()
        cbmp = win32ui.CreateBitmap()
        cbmp.CreateCompatibleBitmap(dc, 100, 100)
        dcmem.SelectObject(cbmp)
        dcmem.SelectObject(cpen)
        dcmem.LineTo((30,30))
        dc.BitBlt((50,0), (50,50), dcmem, (0,0), win32con.SRCCOPY)
        
        self._obj_.OnPaint()

d = Mydialog()
d.DoModal()

VideoCaptureのソースをいじる [python]

[2008-05-23-1]のVideoCaptureのソースをビルドした際のメモ。
WinXP MCE SP2, VS 2003, PFSDK(Windows Server 2003 SP1 SDK)

プロジェクトを開こうとすると古いとか言われたが、指示通り問題なく新しいプロジェクトに変換できた。

C/C++=>全般=>追加のインクルードディレクトリに追加:
C:\Program Files\Microsoft Platform SDK\Samples\Multimedia\DirectShow\BaseClasses

リンカ=>入力=>追加の依存ファイル で、strmbase.libの場所を変更:
上記BaseClassesディレクトリで nmake /f makefile NODEBUG=hoge としてビルド(hogeはたぶん何でもいい)しstrmbase.libを作った上で
"C:\Program Files\Microsoft Platform SDK\Samples\Multimedia\DirectShow\BaseClasses\WIN2000_RETAIL\strmbase.lib"
に変える。


以上でビルドは通る。
関数を増やしたい場合は元ソースの記述をマネして本体を記述し、Dev_methods 変数にそれを加え、VideoCapture.py も適宜変更する。
試しに、getbuffer関数をそっくりコピペしてgetbuffer2と名前を変え、返り値を下記のように変えDev_methodsとVideoCapture.pyを適宜してやってみたが、ちゃんとBITMAPINFOHEADERがpythonから取得できた。(できたvidcap.pydのサイズが配布物(20KB)より小さい(13KB)のはなぜ?)

PyObject *pbmituple;
BITMAPINFOHEADER a = pVideoHeader->bmiHeader;
pbmituple = Py_BuildValue("(k, l,l, H,H, k,k, l,l, k,k)",
  a.biSize, a.biWidth, a.biHeight, a.biPlanes, a.biBitCount,
  a.biCompression, a.biSizeImage, a.biXPelsPerMeter,
  a.biYPelsPerMeter, a.biClrUsed, a.biClrImportant);
PyObject *value;
value = Py_BuildValue("(s#,O)", buffer, size, pbmituple);

[ 前へ ] 1 2 3 4 5 6 7 [ 次へ ]

ChangeLog INDEX
Powered by chalow