Package: bgpy
Running local or remote Python servers in the background using the subprocess
module and establish stream socket-based communication with clients in both
directions.Features:Start and initialize a server process with a simple Python script. Once this
parent script is terminated, the server process continues to run in the
background.Send Python objects between the server and client processes (stored in adict) without worrying about authentication, Python object
serialization, setting up server and client sockets, message length, and
chunksize in the network buffer.Due to the socket-based communication between server and client, it is
possible to resume the communication from any location, as long as access to
the same network is given and the hostname and port on which the server is
listening is known.The communication between client and server is operating system independent
(not like FIFO pipes for example). Furthermore, on Windows it is possible to
communicate between the Windows Subsystem for Linux (WSL) and the Windows
host system using bgpy.Optionally start the server on the remote using the command line interface
(bgpy server <host> <port>), and initialize it from the local client
(initialize(host, port, init_task, exec_task, exit_task)) using
Python.Getting startedInstall the stable release of the package from pypi:pipinstallbgpyDefine tasksRun and intialize a bgpy server on a host, which starts listening
to the provided port. After starting the server, a INIT message with theinit_task,exec_task()andexit_task()tasks are send
to the server in order to complete the initialization.Initialization taskTask that runs once during initialization and can be used to set up the
server. The return value of this function must be a dict, which is then
passed to theexec_taskfunction with every request by a client.definit_task(client_socket:ClientSocket)->dict:init_args={"request_count":0,"value":1000}returninit_argsExecution taskTask that is called each time a request is made by a client to the server.
In this task the message from theexecutemethod of theClientclass is interpreted and an action has to be defined accordingly. The
input of theexec_taskis the return value of the lastexec_taskfunction call (or if never called, the return value from theinit_task). Using the functionrespondom the server, a second
response can be sent to the client after the standard confirmation of the
receipt of the message by the server.defexec_task(client_socket:ClientSocket,init_args:dict,exec_args:dict)->dict:init_args["request_count"]+=1ifexec_args["command"]=="increase":init_args["value"]+=exec_args["value_change"]ifexec_args["command"]=="decrease":init_args["value"]-=exec_args["value_change"]returninit_argsExit taskTask that is executed once if an exit message is sent to the server by
theterminatemethod of theClientclass. The input of theexit_taskis the return value of the lastexec_taskfunction
call (or if never called, the return value from theinit_task). Withresponda second message can be sent to the client, if the client is
set to be waiting for a second response
(Client.terminate(..., await_response=True).defexit_task(client_socket:ClientSocket,init_args:dict,exit_args:dict)->None:init_args["request_count"]+=1init_args["status"]="Exited."respond(client_socket,init_args)returnNoneNote:If the client is set to wait for a second response
(Client.execute(..., await_response=TrueorClient.terminate(..., await_response=True) it is important to handle
this on the server side by sending a response to the client usingrespond. Otherwise the client may be waiting forever as there is no
timeout specified.Run the serverRun an example background process on localhost and send requests using client
sockets:frombgpyimportClient,Serverfrombgpy.example.tasksimportinit_task,exec_task,exit_taskHOST="127.0.0.1"PORT=54321# Optionally set a token for the client authenticationfrombgpyimporttoken_createTOKEN=token_create()# Create server contextserver=Server(host=HOST,port=PORT,token=TOKEN)# Start server in background from contextserver.run_background()# Bind client to server contextclient=Client(host=HOST,port=PORT,token=TOKEN)# Send INIT message from client to server, receive OKresponse=client.initialize(init_task,exec_task,exit_task)# Execute command 'increase' with value on server, receive OKresponse=client.execute({"command":"increase","value_change":10})# Execute command 'decrease' with value on server, receive OKresponse=client.execute({"command":"decrease","value_change":100})# Terminate and wait for response, receive OK with valuesresponse=client.terminate(await_response=True)LicenseThis project is licensed under the MIT License - see the LICENSE file for
details.