python daemon, won't run when called from console script

217 Views Asked by At

I'm using the python-daemon package to create a daemon.

Here is a sample of what I'm doing:

def main():
    import daemon
    import os

    here = os.path.dirname(os.path.abspath(__file__))
    out = open("debug.log", "w+")

    with daemon.DaemonContext(working_directory=here, stdout=out):
        import asyncio

        def handle_client(reader, writer):
            print("client connected")

        async def run():
            server = await asyncio.start_server(
                handle_client, "0.0.0.0", 5555, start_serving=True
            )
            print("Listening")
            async with server:
                await server.serve_forever()

        loop = asyncio.get_event_loop()
        loop.run_until_complete(run())


if __name__ == "__main__":
    main()

So theres 2 ways to run it... by calling the file directly, or by importing the main function and calling it.

It works one way... but not the other.

If I run it like this it works:

python <filenameabove>

However, I'm trying to run this from another python file:

from packagename.otherfile import main

main()

That doesn't work... I get the following error when looking at stderr:

 File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 629, in run_until_complete
    self.run_forever()
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 596, in run_forever
    self._run_once()
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 1854, in _run_once
    event_list = self._selector.select(timeout)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/selectors.py", line 562, in select
    kev_list = self._selector.control(None, max_ev, timeout)
OSError: [Errno 9] Bad file descriptor
1

There are 1 best solutions below

0
David White On

As mentioned in one of the comments, this approach is old and there are better ways to do it. I've since moved to using a process supervisor and all is well.

This still bugged me though.

After doing a bit more research, I found the culprit.

loop = asyncio.get_event_loop()

I changed this to:

loop = asyncio.new_event_loop()

and it works! I thought importing asyncio after the fork would have been fine but needed a new event loop