Simple to use pre-forking server interface.
Spoon can be installed via pip:
pip install spoon
Spoon is compatible with:
- Python 2.7
- Python 3.2+
- PyPy
- PyPy 3
No external dependecies
First create a handle class, that implements the code handling a single
request. The class should inherit from spoon.server.TCPGulp
(for a
TCP server) or spoon.server.UDPGulp
(for a UDP server) and should
implement the handle
method. For example:
import spoon.server class RequestHandler(spoon.server.TCPGulp): def handle(self): request = self.rfile.readline().decode("utf8") response = request.lower().encode("utf8") self.wfile.write(response)
Then implement the server logic by creating a new class the inherits from
the Spoon
or Spork
class MyEchoServer(spoon.server.TCPSpoon): server_logger = "my-echo-server" handler_klass = RequestHandler class MyEchoServerForked(MyEchoServer, spoon.server.TCPSpork): prefork = 6
Then start the normal or forked server:
server = MyEchoServerForked(("::0", 30111)) server.serve_forever()
Then you can send and receive data from that server
>>> import socket >>> connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) >>> connection.connect(("127.0.0.1", 30111)) >>> connection.send("Test") 4 >>> connection.shutdown(socket.SHUT_WR) >>> connection.recv(1024) 'test'
It's usually convenient to run the server as a daemon for this spoon
has a few tools. Simply call the run_daemon
function with you
server:
import spoon.daemon server = MyEchoServerForked(("::0", 30111)) spoon.daemon.run_daemon(server, "/var/tmp/my-echo-server.pid")
To kill the server gracefully you can use the send_action function:
>>> import spoon.daemon >>> spoon.daemon.send_action("stop", "/var/tmp/my-echo-server.pid") >>>
Another useful tool for a daemon is signaling it that the configuration
changed and it should be reloaded without the stopping and starting the
server again. This can be achieved by adding a load_config
method to
the server class:
class MyEchoServer(spoon.server.TCPSpoon): server_logger = "my-echo-server" handler_klass = RequestHandler def load_config(self): # Load some configs for this server # These can be reloaded with SIGUSR1 pass
After that the server can be signaled with the send_action
function:
>>> import spoon.daemon >>> spoon.daemon.send_action("reload", "/var/tmp/my-echo-server.pid") >>>
You can also manage Spork Daemons via the command line with the
spoon.daemon
module. First set your default command line options
in your Spork class. For example:
class MyEchoServer(spoon.server.TCPSpoon): server_logger = "my-echo-server" handler_klass = RequestHandler command_line_defaults = { "port": 30111, "interface": "::0", "pid_file": "/var/tmp/my-echo-server.pid", "log_file": "/var/log/my-echo-server.log", "sentry_dsn": None, "spork": 12, }
Then call the spoon.daemon
via the command line to start/stop/reload
your Spork. Some examples:
$ python -m spoon.daemon echo.server.MyEchoServerForked start $ python -m spoon.daemon echo.server.MyEchoServerForked stop $ python -m spoon.daemon echo.server.MyEchoServerForked restart $ python -m spoon.daemon echo.server.MyEchoServerForked reload
This will automatically take care of:
- Setting up the Spork to fork
- Configuring the interface and port
- Setting the pid file
- Setting up logging
- Starting and detaching the Spork server
The project is licensed under the GNU GPLv2 license.