日の入りで指定のコマンドを実行するPythonスクリプト
日の入りのタイミングで夕焼け小焼けを再生したかったが、
動的に crontab
を書き換えるのも気持ち悪く、at
コマンドも使えなかったので、
かわりにPythonで実装した記録。
やりたいこと
runat.py sunset play -q yuyakekoyake.mp3
とすると、日の入りのタイミングで play -q yuyakekoyake.mp3
を実行する。
あとは、このコマンドをcrontab
に正午くらいにでも放り込んでおけばよい。
つまずき・実装のポイント
argparse でコマンドを受け取る
引数解析はもちろん argparse
にやらせるが、前述の例だと -q
もオプション引数と認識されてしまい、unrecognized arguments
エラーが出る。
これを回避するには、コマンドを受け取る add_argument
メソッドに nargs = argparse.REMAINDER
を指定する。
cf. https://docs.python.org/ja/3.7/library/argparse.html#argparse-remainder
日の出の時刻の計算
ephem
モジュールにお任せしました。
https://pypi.org/project/ephem/
外部コマンドの実行
Pythonに渡された時点でダブルクォート等の空白処理はなされているので、
絶対に os.system(' '.join(args.command))
なんてことはしないこと!
subprocess.run
関数にリストを渡せるので、これを使いましょう。
以下、作ったスクリプト
runat.py
#!/usr/bin/env python
#encoding : utf-8
import sys
import argparse
import logging
import datetime
import time
import subprocess
try:
import ephem
except ModuleNotFoundError:
sys.exit (1)
class choice:
def __init__ (self, star = None, attr = None):
self.star = star
self.attr = attr
CHOICES = {
'sunrise' : choice (star = ephem.Sun, attr = 'next_rising' ),
'sunset' : choice (star = ephem.Sun, attr = 'next_setting'),
'moonrise': choice (star = ephem.Moon, attr = 'next_rising' ),
'moonset' : choice (star = ephem.Moon, attr = 'next_setting'),
}
def main():
parser = argparse.ArgumentParser()
parser.add_argument ('--city', default = 'Tokyo')
parser.add_argument ('--longitude')
parser.add_argument ('--latitude')
parser.add_argument ('--elevation', type = int)
parser.add_argument ('at', choices = CHOICES.keys() )
parser.add_argument ('command', nargs = argparse.REMAINDER)
args = parser.parse_args()
logging.debug ('args = %s' % args)
place = ephem.city (args.city)
if args.latitude is not None:
place.lat = args.latitude
if args.longitude is not None:
place.lon = args.longitude
if args.elevation is not None:
place.elevation = args.elevation
logging.debug ('place = %s' % place)
star = CHOICES[args.at].star()
timeat = getattr(place, CHOICES[args.at].attr) (star)
delta = timeat.datetime() - datetime.datetime.utcnow()
logging.debug ('going at %s' % ephem.localtime(timeat))
try:
time.sleep (delta.seconds)
subprocess.run (args.command)
except KeyboardInterrupt:
sys.exit(1)
if __name__ == '__main__':
main()
#!/usr/bin/env python
#encoding : utf-8
import sys
import argparse
import logging
import datetime
import time
import subprocess
try:
import ephem
except ModuleNotFoundError:
sys.exit (1)
class choice:
def __init__ (self, star = None, attr = None):
self.star = star
self.attr = attr
CHOICES = {
'sunrise' : choice (star = ephem.Sun, attr = 'next_rising' ),
'sunset' : choice (star = ephem.Sun, attr = 'next_setting'),
'moonrise': choice (star = ephem.Moon, attr = 'next_rising' ),
'moonset' : choice (star = ephem.Moon, attr = 'next_setting'),
}
def main():
parser = argparse.ArgumentParser()
parser.add_argument ('--city', default = 'Tokyo')
parser.add_argument ('--longitude')
parser.add_argument ('--latitude')
parser.add_argument ('--elevation', type = int)
parser.add_argument ('at', choices = CHOICES.keys() )
parser.add_argument ('command', nargs = argparse.REMAINDER)
args = parser.parse_args()
logging.debug ('args = %s' % args)
place = ephem.city (args.city)
if args.latitude is not None:
place.lat = args.latitude
if args.longitude is not None:
place.lon = args.longitude
if args.elevation is not None:
place.elevation = args.elevation
logging.debug ('place = %s' % place)
star = CHOICES[args.at].star()
timeat = getattr(place, CHOICES[args.at].attr) (star)
delta = timeat.datetime() - datetime.datetime.utcnow()
logging.debug ('going at %s' % ephem.localtime(timeat))
try:
time.sleep (delta.seconds)
subprocess.run (args.command)
except KeyboardInterrupt:
sys.exit(1)
if __name__ == '__main__':
main()
Author And Source
この問題について(日の入りで指定のコマンドを実行するPythonスクリプト), 我々は、より多くの情報をここで見つけました https://qiita.com/Yasuwo/items/7cb025fb5e0e2ead96e7著者帰属:元の著者の情報は、元の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 .