python-3.4python-daemon

Python3 daemon library


I'm learning Python3, especially the daemon library. I want my daemon to be called with two possible arguments : start & stop.

So far I have this code :

def start():
  with context:
    pidfile = open(Config.WDIR+scriptname+".pid",'w')
    pidfile.write(str(getpid()))
    pidfile.close()
    feed_the_db()

def stop(pid):
  try:
    kill(int(pid),15)
  except ProcessLookupError:
    print("Nothing to kill… (No process with PID "+pid+")")

if __name__ == "__main__":
  scriptname = sys.argv[0]
  context = daemon.DaemonContext(
  working_directory=Config.WDIR,
  pidfile=lockfile.FileLock(Config.WDIR+scriptname),
  stdout=sys.stdout,
  stderr=sys.stderr)
  try:
    if sys.argv[1] == 'start':
      start()
    elif sys.argv[1] == 'stop':
      try:
        pidfile = open(Config.WDIR+scriptname+".pid",'r')
        pid = pidfile.read()
        pidfile.close()
        remove(name+".pid")
        print(name+" (PID "+pid+")")
        stop(pid)
      except FileNotFoundError:
        print("Nothing to kill… ("+scriptname+".pid not found)")
    else:
      print("\nUnknown option : "+sys.argv[1]+"\n\nUsage "+sys.argv[0]+" <start|stop>\n")   
  except IndexError:
    print("\nUsage "+sys.argv[0]+" <start|stop>\n")

It's working but I wonder if I'm doing it the right way.

In particular, why do I have to manually store the PID. Why is it not already contained in the automatically created file :

myhostname-a6982700.3392-7990643415029806679

or the lock file ?


Solution

  • I think you are mixing up the daemon script and the code responsible for managing it.

    Usually in say Ubuntu for example you would control this via upstart

    description "Some Description"
    author "your@email-address.com"
    
    start on runlevel [2345]
    stop on runlevel [!2345]
    
    exec /path/to/script
    

    The actual running python application would never need to store its pid because it always has access to it.

    So what are writing is a script that essentially manages daemon processes , is that really what you want?

    PS: do yourself a favour and get to know the argparse library.

    import argparse
    parser = argparse.ArgumentParser(description='Some Description')
    parser.add_argument('command', help='Either stop or start', choices=['start', 'stop'])
    
    args = parser.parse_args()
    print(args.command)
    

    It is well worth it