はじめまして
個人のブログは西尾泰和のブログ。 ぬるい話は今まで通り個人ブログに書くので、 こちらではラボの業務時間を使って調べたTIPSなどを中心に書いていこうかと思っています。 よろしくお願いします。
個人のブログは西尾泰和のブログ。 ぬるい話は今まで通り個人ブログに書くので、 こちらではラボの業務時間を使って調べたTIPSなどを中心に書いていこうかと思っています。 よろしくお願いします。
これは「位置を指定してそこに文字列を書く」というお絵かき的な方法ですが、 reportlab.platypusを使うと長文を折り返して表示するような書類的な方法も可能です。
# -*- coding: cp932 -*- from reportlab.pdfgen import canvas from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.cidfonts import UnicodeCIDFont fontname = "HeiseiKakuGo-W5" # or "HeiseiMin-W3" pdfmetrics.registerFont(UnicodeCIDFont(fontname)) c = canvas.Canvas("hello.pdf") c.setFont(fontname, 30) c.drawString(100, 675, u"こんにちは世界!") c.showPage() c.save() print "ok."
新人研修にかまけて記事にせずに放置していたところ TokuLog 改め Perl を極めて結婚するブログ - missile on ruby.でリークされてしまいましたが、ワンライナーで作りました。 下のコードを実行すると、動作テストとして三三七拍子を奏でた後、 インタラクティブに操作できるモードになります。
[globals().__setitem__("COMMAND",{'right':[8,0,0,0,0,0,0,0],'d':[2,0,0,0,0,0,0,0], 'f':[16,0,0,0,0,0,0,0],'fire':[16,0,0,0,0,0,0,0],'stop':[0,0,0,0,0,0,0,0],'up':[1, 0,0,0,0,0,0,0],'l':[4,0,0,0,0,0,0,0],'down':[2,0,0,0,0,0,0,0],'s':[0,0,0,0,0,0,0,0 ],'r':[8,0,0,0,0,0,0,0],'u':[1,0,0,0,0,0,0,0],'left':[4,0,0,0,0,0,0,0]})]and[(lamb da f,arg:f(arg,f))((lambda busses,foo:(lambda dev,busses:dev and[globals().__setit em__("dev",dev[0])or globals().__setitem__("conf",dev[0].configurations[0])or glob als().__setitem__("intf",conf.interfaces[0][0])or globals().__setitem__("endpoints ",[e.address for e in intf.endpoints])]or foo(busses[1:]))([d for d in busses[0].d evices if d.idVendor==0x1941 and d.idProduct==0x8021],busses)),__import__("usb").b usses())]and[globals().__setitem__("handle",dev.open())or handle.setConfiguration( conf)or handle.claimInterface(intf)or handle.setAltInterface(intf)]and[globals()._ _setitem__("do",lambda command,time=0.0:[COMMAND.has_key(command)and handle.contro lMsg(0x21,0x09,COMMAND[command],0x2,0x0)]and[time and[__import__("time").sleep(tim e)or do("stop")]])]and[__name__=="__main__"and(lambda Command:[globals().__setitem __(cmd,Command(cmd))for cmd in COMMAND]and globals().__setitem__("FIRE",Command("f ire",6.0)))((lambda cmd,time=0.1:(lambda self:self.__dict__.__setitem__("__repr__" ,lambda:do(cmd,time)and"")or self)(__import__("HTMLParser").HTMLParser())))or[do(x ,3.0/8)or do("s",1.0/8)for x in"uduldudrudududus"]]どう動くのかは下の動画をご覧下さい。
…音と画像が合っていないですね…。
追記:SourceForge.net: PyUSBとpyusbモジュールについて。を参考にしました。
# -*- coding: cp932 -*- """Interface to manupilate MissileLauncher""" __all__ = ["MissileLauncher"] from time import sleep import usb COMMAND = {} def make(x): result = [0] * 8 result[0] = x return result COMMAND["left"] = make(0x4) COMMAND["right"] = make(0x8) COMMAND["up"] = make(0x1) COMMAND["down"] = make(0x2) COMMAND["fire"] = make(0x10) COMMAND["stop"] = make(0x0) short = {} for k in COMMAND: short[k[0]] = COMMAND[k] COMMAND.update(short) class UsbDevice: def __init__(self, vendor_id, product_id): busses = usb.busses() self.handle = None for bus in busses: devices = bus.devices for dev in devices: if dev.idVendor == vendor_id and dev.idProduct == product_id: self.dev = dev self.conf = self.dev.configurations[0] self.intf = self.conf.interfaces[0][0] self.endpoints = [e.address for e in self.intf.endpoints] return raise RuntimeError('Device not found.') def open(self): if self.handle: self.handle = None handle = self.dev.open() handle.setConfiguration(self.conf) handle.claimInterface(self.intf) handle.setAltInterface(self.intf) self.handle = handle class MissileLauncher: def __init__(self): dev = UsbDevice(0x1941, 0x8021) dev.open() self.dev = dev def do(self, command, time = 0.0): if not COMMAND.has_key(command): return -1 self.dev.handle.controlMsg( 0x21, 0x09, COMMAND[command], 0x2, 0x0) if time: sleep(time) self.do("stop") def putCommandInGlobals(): class Command(object): def __init__(self, cmd, time = 0.1): self.cmd = cmd self.time = time def __repr__(self): m.do(self.cmd, self.time) return "" for cmd in COMMAND: globals()[cmd] = Command(cmd) globals()["FIRE"] = Command("fire", 6.0) def test(): def do(a, t = 0.5): m.do(a, t * 0.75) m.do("stop", t * 0.25) [do(x) for x in "uduldudrudududus"] if __name__ == "__main__": m = MissileLauncher() putCommandInGlobals() test() print "ok."
UDP Broadcast Server : UDP : Network : Python examples (example source code) Organized by topic を見たところ、簡単に実装できそうだったので、実際に動かして勉強することにしました。 結果、サーバが25行、クライアントが27行になりました。
素直に書いてしまうとサーバから何も送られてこない時にクライアントが待機状態に入ってしまって ハングアップしたように見えてしまいます。 UNIXではノンブロッキングモードというそうならないモードがあるようですが、 Windowsでは使えないので、selectモジュールを使ってブロックされないようにしました。
あとクライアント側で、データが来たかどうかにかかわらず同じ長さsleepしていると、 サーバがデータを送る頻度が高いときにどんどん取り残されていくので、 データが来ていたときにはsleepしないですぐ「次のデータは来ているかな?」とチェックするようにしました。
見よう見まねのコードですが、作っていて自分がだいぶ勉強になったのでシェアしたいと思います。 「そこは違う!」などのつっこみは大歓迎します。
サーバのコードがこちら。
import socket, traceback from time import sleep host = '' # Bind to all interfaces port = 51423 address = "10.89.107." s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) s.bind((host, port)) count = 0 while True: try: s.sendto(str(count), (address + "255", port)) print "sent", count sleep(0.8) count += 1 except (KeyboardInterrupt, SystemExit): break except: traceback.print_exc() break
クライアントのコードがこちら。
import socket, traceback from select import select from time import sleep host = '' # Bind to all interfaces port = 51423 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((host, port)) while True: try: ins, outs, errs = select([s], [], [], 0) if ins: for i in ins: message, address = i.recvfrom(8192) print "message:", message, "from", address else: print "none..." sleep(1) except (KeyboardInterrupt, SystemExit): break except: traceback.print_exc() break
このサーバスクリプトを1台のマシンで走らせ、 クライアントを複数のマシンで走らせてみると、 きちんと一つのプログラムが送り出した情報を複数のプログラムが受け取っていることがわかります。 めでたしめでたし。
PythonからUSBミサイルランチャーを操作するためには、 libusb-win32とPyUSBというモジュールをインストールする必要があります。 pyusbモジュールについて。 というページでWindows版のインストーラが公開されているので、 それを使うと簡単にインストールできます。
インストールが完了して、USBミサイルランチャーを接続したら、 下の34行のスクリプトを実行すると 上下左右に移動した後発射されるはずです。
VENDER_ID = 0x1941 PRODUCT_ID = 0x8021 def find(vendor_id, product_id): import usb busses = usb.busses() for bus in busses: for dev in bus.devices: if dev.idVendor == vendor_id and dev.idProduct == product_id: return dev raise RuntimeError('Device not found.') dev = find(VENDER_ID, PRODUCT_ID) conf = dev.configurations[0] interface = conf.interfaces[0][0] handle = dev.open() handle.setConfiguration(conf) handle.claimInterface(interface) handle.setAltInterface(interface) def do(command, time = 0.0): handle.controlMsg(0x21, 0x09, command, 0x2, 0x0) if time: from time import sleep sleep(time) do([0, 0, 0, 0, 0, 0, 0, 0]) # stop do([1, 0, 0, 0, 0, 0, 0, 0], 1.0) # up do([2, 0, 0, 0, 0, 0, 0, 0], 1.0) # down do([4, 0, 0, 0, 0, 0, 0, 0], 1.0) # left do([8, 0, 0, 0, 0, 0, 0, 0], 1.0) # right do([16, 0, 0, 0, 0, 0, 0, 0], 6.0) # fire
下のコードを実行するとその下のように出力されます。
>>> multiline(""" [foo] [bar] [baz] hoge [/baz] [/bar] [/foo] """)
'\n'.join([ '[foo]', ' [bar]', ' [baz]', ' hoge', ' [/baz]', ' [/bar]', '[/foo]',])
逆に、この出力の前にprintとつけて実行すると元に戻ります。
>>> print '\n'.join([ '[foo]', ' [bar]', ' [baz]', ' hoge', ' [/baz]', ' [/bar]', '[/foo]',])
[foo] [bar] [baz] hoge [/baz] [/bar] [/foo]
ソースは以下のようになります。たいしたことはしてません。
def multiline(s): s = s.strip("\n") print ("'\\n'.join([\n" + "\n".join(" %s," % `x` for x in s.split("\n")) + "])")
個人的には全ての行末に\nがつくのと、 頭に"\n".joinがつくのでは後者の方がマシだと思っているのですが、 そうでない人には下のコードの方がいいかもしれません。
>>> def multiline(s): s = s.strip("\n") print "\n".join( r" %s\n'" % `x`[:-1] for x in s.split("\n"))これだと下のように出力されます。 Pythonでは隣接する文字列リテラルが結合されるので この複数行の状態のまま普通に使って問題なく動きます。
>>> multiline(""" [foo] [bar] [baz] hoge [/baz] [/bar] [/foo] """) '[foo]\n' ' [bar]\n' ' [baz]\n' ' hoge\n' ' [/baz]\n' ' [/bar]\n' '[/foo]\n'
最後になりましたが、 4.8 textwrap -- テキストの折り返しと詰め込みのdedentを使うというのも一つの手ですね。