Pythonプログラムのcattコマンドを高速化する
cattとは
cattはPythonで書かれたプログラムで、指定したURLの音楽・動画・WebページをGoogle Chromecast/Home/Nest Hubで再生・表示させることができます。
Raspberry Piからcattコマンドを実行することで、Google Homeに音声メッセージを再生させたり、Nest Hubに好きなWebページを表示させたりできるので、DIYスマートホームシステムを作るのに役立ちます。
cattの問題点 - 起動が遅い
高機能なのですが、起動がかなりもっさりしています。ボトルネックになっているのはPhtonモジュールのimportで、以下のようにRaspberry Pi4でも一秒以上。Raspberry Pi3では2秒弱の時間がかかっています。通常の動画再生ならそれほど気になりませんが、スマートホーム用に使うとなると1秒でもレスポンスを早くしたいところです。
PYTHONPROFILEIMPORTTIME=1 catt -d 192.168.x.xxx cast_site https://www.google.com
:
import time: 1652 | 795904 | youtube_dl
import time: 976 | 796880 | catt.stream_info
import time: 2753 | 1213944 | catt.controllers
import time: 1570 | 1570 | catt.http_server
import time: 711 | 711 | catt.subs_info
import time: 6028 | 1296239 | catt.cli
高速化の方法
cattコマンド相当のサービスをPythonで作成する
importでの起動待ち時間の影響をなくすために、catt相当のサービス(Pythonで記述)をあらかじめ立ち上げておくことにします。コマンドラインのオプション処理を自前で行う必要があるかと思ったのですが、click.testing.CliRunner
というテスト用のメソッドを使って、catt本来のコマンドラインオプション処理を流用することができました。
以下が作成したサービスプログラムです。port 50007に、cattコマンドと同じコマンドラインパラメータを送信すると処理してくれます。
なお、終了時に子プロセスを終了させるため、psutilモジュールを使用しています。pip3 install psutil
でインストールをお願いします。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# catt_service : Service to launch catt
import os
import socket
import signal
import sys
import syslog
import traceback
import psutil
from click.testing import CliRunner
from catt.cli import get_config_as_dict
from catt.cli import cli
def onexit(signum, stack):
syslog.syslog('stopped')
for child in psutil.Process(os.getpid()).children():
child.kill()
sys.exit()
HOST = '' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(5)
syslog.syslog('started. port=' + str(PORT))
while True:
conn, addr = s.accept()
syslog.syslog('connected from' + str(addr))
pid = os.fork()
if pid != 0:
signal.signal(signal.SIGHUP, onexit)
signal.signal(signal.SIGINT, onexit)
signal.signal(signal.SIGQUIT, onexit)
signal.signal(signal.SIGTERM, onexit)
else:
try:
#conn.setTimeout(3)
data = conn.recv(1024)
conn.close()
if data:
syslog.syslog('args: ' + data.decode('utf-8'))
#args = data.decode('utf-8').split()
runner = CliRunner()
result = runner.invoke(cli, data.decode('utf-8'), obj=get_config_as_dict())
syslog.syslog('catt exit code {0:d}, output: {1}'.format(result.exit_code, result.output))
else:
pass# syslog.syslog(syslog.LOG_INFO, 'no data received')
sys.exit()
except Exception as e:
syslog.syslog(syslog.LOG_ERR, 'exception:' + traceback.format_exc())
conn.close()
sys.exit()
サービスの登録と実行
- serviceファイルの作成
[Unit]
Description=Catt - Cast All The Things - Service
[Service]
ExecStart=/home/pi/bin/catt_service.py
KillMode=process
Restart=always
[Install]
WantedBy=multi-user.target
- catt serviceを有効化する
sudo systemctl daemon-reload
sudo systemctl enable catt.service
sudo systemctl start catt.service
- catt serviceが実行されていることを確認
sudo systemctl status catt.service
動作確認
- まずnetcatをインストール
sudo apt-get -y install netcat
- port 50007 にコマンドライン内容を送信。以下の例ではNest HubにGoogleのホームページを表示させて見ます。
nc localhost 50007
-d <Google Nest HubのIPアドレス> cast_site https://www.google.co.jp
自分の場合、実際にはnode-redのtcp outノードを使ってGoogle Nest HubへWebページの表示リクエストを行ってます。
Author And Source
この問題について(Pythonプログラムのcattコマンドを高速化する), 我々は、より多くの情報をここで見つけました https://qiita.com/tinoue@github/items/98ecdf223ed5cbc46b76著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .