[pukiwiki]
[[こちらの記事の続き:http://boxheadroom.com/2009/10/14/mathlink_weatherdata_1]]
無料のMathematicaPlayerをIronPython2.6RC1を使い、Webアプリとして動かしてみました。
こちらの記事を参考にしてさせて頂きました(というか、ほぼ引き写し)
-[[無料配布MathematicaカーネルとNET Framework実装IronRubyでグリッド・Matheatica計算環境は5分で作れる:http://www.hirax.net/diaryweb/2009/10/06.html#8400]]
-[[WSGIとPythonでスマートなWebアプリケーション開発を 第3回 WSGIミドルウェアの作成:http://gihyo.jp/dev/feature/01/wsgi/0003]]
-[[Python ライブラリリファレンス wsgiref — WSGI ユーティリティとリファレンス実装:http://www.python.jp/doc/2.5/lib/module-wsgiref.html]]
すごく久々にサーバのスクリプトを書きました
[/pukiwiki]
[pukiwiki]
ホントは、何か既存のWebフレームワークを使おうと思ったのですが、頭がこんがらがったので上記の記事を参考にしてテキトー作成。
localhostからのアクセスしか考えてないので、セキュリティ周りははしょってあります。(というか、どうしたら安全なのか判らず)
あくまで自分の勉強用コードということで。。。
*使い方
コマンドプロンプトにて
ipy MathematicaServer.py
として起動。
http://localhost:8000/evaluation/式
式をMathematicaPlayerで評価
プレーンテキストとして結果が返ってきます。
/restart MathLinkを再起動
/shutdown サーバを終了
CPythonからWeb API経由で呼び出すためのモジュールを書くとCGソフトのBlenderなどからも使えて便利かも。
(分散処理しないなら子プロセスのほうが簡単だったかしらん?)
例)
http://localhost:8000/evaluate/WeatherData[{“Gifu”,”Japan”},”Temperature”]
14.4 #岐阜の現在気温 14.4℃が返ってきました。
以下コード
[/pukiwiki]
まずは、URLに応じて関数を呼ぶためのディスパッチャ(WSGIのミドルウェア)とユーティリティ関数。
app.pyとして保存。
こちらは、IronPythonでもCPython2.5でも動きました
#-*- coding:utf-8 -*-
"""
app.py
original source
WSGIとPythonでスマートなWebアプリケーション開発を
第3回 WSGIミドルウェアの作成
http://gihyo.jp/dev/feature/01/wsgi/0003
"""
from wsgiref import util, simple_server
class const(object):
name = 'SCRIPT_NAME'
info = 'PATH_INFO'
def header(start_response):
start_response('200 OK', [('Content-type', 'text/plain')])
def notFound(environ, start_response):
start_response("404 NotFound",[('Content-type', 'text/plain')])
return '%s is not found' % util.request_uri(environ)
class SelectApp(object):
u''' パスによるアプリケーション振り分け'''
def __init__(self,notfound=notFound):
# 割り振るパスが見つからなかったときに呼び出すアプリケーション
self.notfound = notfound
self.table=[]
self.flag=True
def dispatch(self,path):
def _(app):
self.table.append( (path,app))
return app
return _
def __call__(self, environ, start_response):
u''' リクエストのパスを見て振り分ける '''
scriptname,pathinfo=name_info(environ)
for p, app in self.table:
if p == '' or p == '/' and pathinfo.startswith(p):
return app(environ, start_response)
if pathinfo == p or pathinfo.startswith(p) and \
pathinfo[len(p)] == '/':
fetchone(environ,p)
#scriptname,pathinfo=name_info(environ)
return app(environ, start_response)
return self.notfound(environ, start_response)
def name_info(environ):
scriptname = environ.get(const.name, '')
pathinfo = environ.get(const.info, '')
return scriptname,pathinfo
def fetchone(environ,p=""):
scriptname,pathinfo=name_info(environ)
if not p:
plist=pathinfo.split("/")
p=plist.pop(0)
scriptname+= p
pathinfo=pathinfo[len(p):]
environ[const.name] =scriptname
environ[const.info] = pathinfo
return p
こちらはIronPython専用
MathematicaServer.pyとして保存。
#-*- coding:utf-8 -*-
"""
MathematicaServer.py
original source
無料配布MathematicaカーネルとNET Framework実装IronRubyで
グリッド・Matheatica計算環境は5分で作れる
http://www.hirax.net/diaryweb/2009/10/06.html#8400
"""
import clr , System
require=clr.AddReferenceToFile
#require=clr.AddReferenceByName
require("Wolfram.NETLink")
from Wolfram.NETLink import *
import sys
from app import *
from wsgiref import simple_server
mlpath="-linkmode launch -linkname "
#full path to mathkernel.exe
mlpath+=" 'C:\\Program Files\\Wolfram Research\\Mathematica Player\\7.0\\mathkernel.exe' "
class Mathematica(object):
def open(self):
self.kernelLink=MathLinkFactory.CreateKernelLink(mlpath)
self.kernelLink.WaitAndDiscardAnswer()
def do(self,command):
return self.kernelLink.EvaluateToInputForm(command, 0)
def close(self):
self.kernelLink.EvaluateToInputForm('MVClose[]', 0)
self.kernelLink.Close()
app = SelectApp()
dispatch=app.dispatch
@dispatch("/restart")
def restart(environ,start_response):
header(start_response)
m.close()
m.open()
return "OK"
@dispatch("/evaluate")
def evaluate(environ,start_response):
scriptname,pathinfo=name_info(environ)
if pathinfo :
ret= m.do(pathinfo[1:])
header(start_response)
return ret
else :
return notFound(environ,start_response)
@dispatch("/shutdown")
def shutdown(environ,start_response):
app.flag=False
header(start_response)
return "Shutdown"
if __name__ == '__main__':
import threading,time
def watch():
while app.flag :
time.sleep(1.)
m=Mathematica()
m.open()
srv = simple_server.make_server('127.0.0.1', 8000, app)
th=threading.Thread(target=srv.serve_forever)
th.setDaemon(False)
w=threading.Thread(target=watch)
w.setDaemon(True)
w.start()
th.start()
w.join()
th.join(1.)
sys.exit()
shutdownまわりがゴチャゴチャしております。