Python で WEB Server > 諦めて apache
Python で簡単にWEBサーバーを立てられるので、試す。
Lチカを目指します!
SimpleHTTPServer
CGIは動かないシンプルなもの。
Python 2系列
$ sudo python -m SimpleHTTPServer 80
CGIHTTPServer
CGIが動きます。
$ sudo python -m CGIHTTPServer 80
ファイル作成
#!/usr/bin/env python # -*- coding: utf-8 -*- import cgitb cgitb.enable() print "Content-Type: text/html;charset=utf-8" print print "Hello World!"
パーミッションを 755 にする
$ chmod 755 index.py
GPIO を触る
せっかくのpython なので、GPIO も触ってみる。
ところが import RPi.GPIO as GPIO
などすると、ROOT で実行しなさいとエラーが出る。
これは、 nobody で cgi が起動しているからだ。
20.20. CGIHTTPServer — CGI 実行機能付き HTTP リクエスト処理機構 — Python 2.7.13 ドキュメント
さて、どうしたものか・・・。
試したこと その1(NG)
nobody を group gpio に入れる
コマンドラインからは、 sudo -u nobody ./index.py などで動作するが、cgi からは動かない。
print(os.getuid()) commands.getoutput("cat /sys/class/gpio/gpio4/value")
で、 nobody (65534) で有ることの確認をとりつつ動かしましたが、
cat: /sys/class/gpio/gpio4/value: 許可がありません
を、得る。
どこで止まっているのか不明。
試したこと その2(NG)
Python3 で試す。
pip3 install wiringpi2
sudo python3 -m http.server –cgi 80
FileNotFoundError: [Errno 2] No such file or directory: ‘cat /sys/class/gpio/gpio4/value’
/bin/cat: /sys/class/gpio/gpio4/value: 許可がありません
諦めて apache
諦めて apache2 でやります。
- apache2 install
- mod python とか色々入れます
$ sudo apt-get install libapache2-mod-python
/etc/apache2/envvars
実行ユーザを変えてしまう
/etc/apache2/envvars
で、
export APACHE_RUN_USER=pi export APACHE_RUN_GROUP=pi
などしてしまう。
<Directory /home/pi/public_html> Options Indexes FollowSymLinks AllowOverride None Require all granted AddHandler mod_python .py PythonHandler mod_python.publisher PythonDebug On Options +ExecCGI AddHandler cgi-script .py </Directory>
ハマり所
cgi-bin の許可
permission 755 にし忘れる
これで、GPIOに触れる様になった。
ただし、GPIOの初期設定には、やはりroot権限が必要なのが注意だ。
コーディングとアパッチの圧縮OFF
手順
$ cat ../set_gpio_pins.sh #!/bin/bash /usr/local/bin/gpio export 4 out /usr/local/bin/gpio -g mode 4 out
チカチカ終了を待たずに、htmlを吐き出せるように、スレッドを使用しています。
ここで注意が必要なのは、Pythonレベルでバッファリングを指定無くても、Apacheは、初期設定のまま使っていると、Gzip圧縮してくれるので、結果的にバッファリングされます。
# cat /etc/apache2/mods-enabled/deflate.conf <IfModule mod_deflate.c> <IfModule mod_filter.c> # these are known to be safe with MSIE 6 # Changed #AddOutputFilterByType DEFLATE text/html text/plain text/xml # everything else may cause problems with MSIE 6 AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ecmascript AddOutputFilterByType DEFLATE application/rss+xml AddOutputFilterByType DEFLATE application/xml </IfModule> </IfModule>
text/html に対して、圧縮をOFFにしました。
それを前提のコード。
#!/usr/bin/python -u # -*- coding: utf-8 -*- import sys import wiringpi as wp import time import threading from datetime import datetime import cgi import cgitb cgitb.enable() PIN = 4 class MyThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): time.sleep(1) io = wp.GPIO(wp.GPIO.WPI_MODE_GPIO_SYS) # WPI_MODE_PINS WPI_MODE_GPIO WPI_MODE_GPIO_SYS WPI_MODE_PHYS WPI_MODE_PIFACE counter = 0 while counter < 10: io.digitalWrite(PIN,io.HIGH) time.sleep(0.2) io.digitalWrite(PIN,io.LOW) time.sleep(0.2) counter += 1 th = MyThread() th.setDaemon(True) th.start() form = cgi.FieldStorage() action = form.getvalue('action','') print("Content-Type: text/html;charset=utf-8") print("\r\n\r\n") print(""" <html> <body> <a href="?action=led">LED</a> {action} </body> </html> """[1:-1].format(**vars())) print( datetime.now().strftime("%Y/%m/%d %H:%M:%S") ) th.join()
ちゃんと、先にHTMLが出力されてから、チカチカします。