Pythonプログラム用の非常にシンプルなHTML/AJAXベースのGUIを作成したいので、フロントエンドはAJAXを介してプログラムと通信するHTMLページです。 python SimpleHTTPServer.SimpleHTTPRequestHandler
?
簡単な例は、テキストフィールドとボタンです。ボタンが押されると、フィールドの内容がサーバーに送信され、サーバーは対応する応答を送り返します。 Pythonにはこのための強力なソリューションがたくさんあることは承知していますが、これは非常にシンプルにしたいと思います。私はすでにそのようなサーバーの素敵な例をいくつか見つけました(例 here )が、これまでのところ、本当に最小限のサーバーを思い付くことができませんでした。
なぜGUIをこのような方法で実装したいのか疑問に思う方のために:このアプリケーションの私の焦点は、最小限の操作でニースレイアウトで大量のデータを表示することです。非インタラクティブなデータ表示に使用します)。
わかりました、これで自分の質問に答えられると思います。サーバー上で数値の2乗を計算するための実装例を次に示します。改善や誤解がある場合はお知らせください。
pythonサーバーファイル:
import threading
import webbrowser
import BaseHTTPServer
import SimpleHTTPServer
FILE = 'frontend.html'
PORT = 8080
class TestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
"""The test example handler."""
def do_POST(self):
"""Handle a post request by returning the square of the number."""
length = int(self.headers.getheader('content-length'))
data_string = self.rfile.read(length)
try:
result = int(data_string) ** 2
except:
result = 'error'
self.wfile.write(result)
def open_browser():
"""Start a browser after waiting for half a second."""
def _open_browser():
webbrowser.open('http://localhost:%s/%s' % (PORT, FILE))
thread = threading.Timer(0.5, _open_browser)
thread.start()
def start_server():
"""Start the server."""
server_address = ("", PORT)
server = BaseHTTPServer.HTTPServer(server_address, TestHandler)
server.serve_forever()
if __name__ == "__main__":
open_browser()
start_server()
...そしてHTMLファイル(私は 'frontend.html'と呼んでいますが、残念ながら名前はJavaScriptコードにも表示される必要があります):
<html>
<head>
<title>AJAX test</title>
</head>
<body>
<script type="text/javascript">
function xml_http_post(url, data, callback) {
var req = false;
try {
// Firefox, Opera 8.0+, Safari
req = new XMLHttpRequest();
}
catch (e) {
// Internet Explorer
try {
req = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
req = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {
alert("Your browser does not support AJAX!");
return false;
}
}
}
req.open("POST", url, true);
req.onreadystatechange = function() {
if (req.readyState == 4) {
callback(req);
}
}
req.send(data);
}
function test_button() {
var data = document.test_form.test_text.value;
xml_http_post("frontend.html", data, test_handle)
}
function test_handle(req) {
var elem = document.getElementById('test_result')
elem.innerHTML = req.responseText
}
</script>
<form name=test_form>
sqr(
<input type="text" name="test_text" value="0" size="4">
) =
<span id="test_result">0</span>
<input type=button onClick="test_button();" value="start" title="start">
</form>
</body>
</html>
もちろん、XMLリクエストに jQuery を使用する方がはるかに便利ですが、簡単にするために、このままにしておきます。
最後に、WSGIを使用した代替実装(残念ながら、リクエストがPOSTでない場合に、標準のファイルサービスハンドラーに頼る方法がありませんでした):
import threading
import webbrowser
from wsgiref.simple_server import make_server
FILE = 'frontend.html'
PORT = 8080
def test_app(environ, start_response):
if environ['REQUEST_METHOD'] == 'POST':
try:
request_body_size = int(environ['CONTENT_LENGTH'])
request_body = environ['wsgi.input'].read(request_body_size)
except (TypeError, ValueError):
request_body = "0"
try:
response_body = str(int(request_body) ** 2)
except:
response_body = "error"
status = '200 OK'
headers = [('Content-type', 'text/plain')]
start_response(status, headers)
return [response_body]
else:
response_body = open(FILE).read()
status = '200 OK'
headers = [('Content-type', 'text/html'),
('Content-Length', str(len(response_body)))]
start_response(status, headers)
return [response_body]
def open_browser():
"""Start a browser after waiting for half a second."""
def _open_browser():
webbrowser.open('http://localhost:%s/%s' % (PORT, FILE))
thread = threading.Timer(0.5, _open_browser)
thread.start()
def start_server():
"""Start the server."""
httpd = make_server("", PORT, test_app)
httpd.serve_forever()
if __name__ == "__main__":
open_browser()
start_server()
WSGIリファレンス実装 を使用します。長い目で見れば、あなたは幸せになるでしょう。
from wsgiref.simple_server import make_server, demo_app
httpd = make_server('', 8000, demo_app)
print "Serving HTTP on port 8000..."
# Respond to requests until process is killed
httpd.serve_forever()
Demo_appは比較的簡単に記述できます。 Ajaxリクエストを処理します。
これは、@ = owの例に基づいたPython 3の簡単な例です。
エラーが発生する可能性があることはわかっていますが、エラーが見つかった場合はコメントしてください。
実行をクリックすると、コードは文字列「I send you this message」を送信し、pythonは「I got it」で応答します
HTMLコード
(これにはjsコンソールを使用する必要があります)
<body>
<button id="runButton">Run</button>
<script type="text/javascript">
function xml_http_post(url, data) {
var req = new XMLHttpRequest();
req.open("POST", url, true);
req.onreadystatechange = function() {
if (req.readyState == 4) {
console.log(req.responseText);
}
}
req.send(data);
}
function runbuttonfunc() {
xml_http_post("frontend.html", "I sent you this message")
}
document.getElementById("runButton").onclick = runbuttonfunc;
</script>
</body>
Pythonコード:http.serverをインポートする
FILE = 'frontend.html'
PORT = 8000
class TestHandler(http.server.SimpleHTTPRequestHandler):
"""The test example handler."""
def do_POST(self):
"""Handle a post request by returning the square of the number."""
print(self.headers)
length = int(self.headers.get_all('content-length')[0])
print(self.headers.get_all('content-length'))
data_string = self.rfile.read(length)
print(data_string)
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.flush_headers()
self.wfile.write("I got it!".encode())
def start_server():
"""Start the server."""
server_address = ("", PORT)
server = http.server.HTTPServer(server_address, TestHandler)
server.serve_forever()
start_server()
非常に直感的な例をありがとう@nikow私はあなたの例を試そうとしていましたが、エラーが発生しました:
(プロセス:10281):GLib-CRITICAL **:g_slice_set_config:assertion 'sys_page_size == 0' failed
私のニーズに合わせてコードを変更しました。
webbrowser.open('file:///home/jon/workspace/webpages/frontend_example/%s' % FILE)
// skipped the port part
httpd = make_server("", 8080, test_app)
// hardcoded it here.
hTMLファイルをWebサーバーに配置する必要がありますか?私はまだそこに入れていません!。