import time
from fastcore.parallel import threaded
from pathlib import Path
from socketserver import UnixStreamServer
serve
CmdHandler
CmdHandler (request, client_address, server)
Run self.server.cmd
with request’s argv
and stdin
; return stdout
and stderr
CmdHandler’s primary use-case is together with a server inheriting CmdMixin, however it supports any socketserver.BaseServer
that has a cmd
attribute. If the server also has a pool
it’s used to execute cmd
.
Here’s an example of how to use CmdHandler. First, define the command. It should have no arguments itself but rather parse its arguments from sys.argv
. Its return value isn’t used, instead it should write to stdout
.
def _cmd():
+sys.argv[1])
sys.stdout.write(sys.stdin.read()'Error!') sys.stderr.write(
Then define a server with a cmd
attribute:
class _CmdServer(UnixStreamServer): cmd = lambda x: _cmd()
Start the server. We start it with handle_request
in a separate thread:
= Path('fdaemon.sock')
p if p.exists(): p.unlink()
@threaded
def _f():
with _CmdServer(str(p), CmdHandler) as srv: srv.handle_request()
_f()0.2) # wait for server to start time.sleep(
…so that we can send a request and print its response:
'Hello, ', 'world!'], str(p)) transfer([
len(stdin)=7 argv=['<lambda>', 'world!']
['Hello, world!', 'Error!']
CmdMixin
CmdMixin (server_address, cmd, pool=None, RequestHandlerClass=<class'__main__.CmdHandler'>, timeout=None, **kwargs)
Socket server with a cmd
and optional pool
class CmdUnixServer(CmdMixin, ThreadingUnixStreamServer): pass
= Path('fdaemon.sock')
p if p.exists(): p.unlink()
@threaded
def _f():
with ProcessPoolExecutor() as pool, CmdUnixServer(str(p), _cmd, pool) as srv: srv.handle_request()
_f()0.2) # wait for server to start time.sleep(
'Hello, ', 'world!'], str(p)) transfer([
len(stdin)=7 argv=['_cmd', 'world!']
['Hello, world!', 'Error!']
CmdTCPServer
CmdTCPServer (server_address, cmd, pool=None, RequestHandlerClass=<class'__main__.CmdHandler'>, timeout=None, **kwargs)
Socket server with a cmd
and optional pool
A convenient wrapper to instantiate and start a CmdTCPServer that handles requests until it’s interrupted or times out. Here’s the previous example using _fastdaemon_serve
. We’ve also set a timeout
to avoid running forever:
= 'localhost',9999
host,port
@threaded
def _f(): _fastdaemon_serve(_cmd, port, host, timeout=1)
_f()0.4) # wait for server to start time.sleep(
'Hello, ', 'world!'], port, host) transfer([
len(stdin)=7 argv=['_cmd', 'world!']
['Hello, world!', 'Error!']
'nbdev.clean:nbdev_clean') _import_cmd(
<function nbdev.clean.nbdev_clean(fname: str = None, clear_all: bool = False, disp: bool = False, stdin: bool = False)>
fastdaemon_serve
fastdaemon_serve (cmd:str, port:int, host:str='localhost', timeout:int=None)
Serve cmd
on port
, with optional host
and timeout
Type | Default | Details | |
---|---|---|---|
cmd | str | Module path to callable command (example: pkg.mod:obj) | |
port | int | Server port | |
host | str | localhost | Server host |
timeout | int | None | Shutdown after timeout seconds without requests |
!fastdaemon_serve -h
usage: fastdaemon_serve [-h] [--host HOST] [--timeout TIMEOUT] cmd port
Serve `cmd` on `port`, with optional `host` and `timeout`
positional arguments:
cmd Module path to callable command (example: pkg.mod:obj)
port Server port
optional arguments:
-h, --help show this help message and exit
--host HOST Server host (default: localhost)
--timeout TIMEOUT Shutdown after `timeout` seconds without requests