{"id":24182078,"url":"https://github.com/munterfi/bgpy","last_synced_at":"2025-09-21T03:31:39.378Z","repository":{"id":37079252,"uuid":"318573031","full_name":"munterfi/bgpy","owner":"munterfi","description":"Running local or remote python servers in the background and establish stream socket-based communication with clients.","archived":false,"fork":false,"pushed_at":"2024-07-06T00:34:22.000Z","size":905,"stargazers_count":4,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-12-30T02:07:17.606Z","etag":null,"topics":["background","popen","process-communication","python3","server","sockets","subprocess"],"latest_commit_sha":null,"homepage":"https://bgpy.readthedocs.io/en/latest/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/munterfi.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.rst","contributing":"CONTRIBUTING.rst","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2020-12-04T16:27:56.000Z","updated_at":"2024-12-16T23:16:20.000Z","dependencies_parsed_at":"2023-01-29T01:15:12.502Z","dependency_job_id":"f24fe21e-47d3-428e-9d97-86859394953d","html_url":"https://github.com/munterfi/bgpy","commit_stats":{"total_commits":198,"total_committers":3,"mean_commits":66.0,"dds":"0.41414141414141414","last_synced_commit":"7646ce4883d561d9463756b589be9ec8291e7f6d"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/munterfi%2Fbgpy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/munterfi%2Fbgpy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/munterfi%2Fbgpy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/munterfi%2Fbgpy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/munterfi","download_url":"https://codeload.github.com/munterfi/bgpy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":233707208,"owners_count":18717386,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["background","popen","process-communication","python3","server","sockets","subprocess"],"created_at":"2025-01-13T07:27:19.477Z","updated_at":"2025-09-21T03:31:34.084Z","avatar_url":"https://github.com/munterfi.png","language":"Python","readme":"\n====\nbgpy\n====\n\n.. image:: https://img.shields.io/pypi/v/bgpy.svg\n        :target: https://pypi.python.org/pypi/bgpy\n\n.. image:: https://github.com/munterfi/bgpy/workflows/check/badge.svg\n        :target: https://github.com/munterfi/bgpy/actions?query=workflow%3Acheck\n\n.. image:: https://readthedocs.org/projects/bgpy/badge/?version=latest\n        :target: https://bgpy.readthedocs.io/en/latest/\n        :alt: Documentation Status\n\n.. image:: https://codecov.io/gh/munterfi/bgpy/branch/master/graph/badge.svg\n        :target: https://codecov.io/gh/munterfi/bgpy\n\n\nRunning local or remote Python servers in the background using the subprocess\nmodule and establish stream socket-based communication with clients in both\ndirections.\n\nFeatures:\n\n* Start and initialize a server process with a simple Python script. Once this\n  parent script is terminated, the server process continues to run in the\n  background.\n* Send Python objects between the server and client processes (stored in a\n  :code:`dict`) without worrying about authentication, Python object \n  serialization, setting up server and client sockets, message length, and\n  chunksize in the network buffer.\n* Due to the socket-based communication between server and client, it is\n  possible to resume the communication from any location, as long as access to\n  the same network is given and the hostname and port on which the server is\n  listening is known.\n* The communication between client and server is operating system independent\n  (not like FIFO pipes for example). Furthermore, on Windows it is possible to\n  communicate between the Windows Subsystem for Linux (WSL) and the Windows\n  host system using bgpy.\n* Optionally start the server on the remote using the command line interface\n  (:code:`bgpy server \u003chost\u003e \u003cport\u003e`), and initialize it from the local client\n  (:code:`initialize(host, port, init_task, exec_task, exit_task)`) using\n  Python.\n\nGetting started\n---------------\n\nInstall the stable release of the package from pypi:\n\n.. code-block:: shell\n\n    pip install bgpy\n\nDefine tasks\n^^^^^^^^^^^^\n\nRun and intialize a bgpy server on a host, which starts listening\nto the provided port. After starting the server, a INIT message with the\n:code:`init_task`, :code:`exec_task()` and :code:`exit_task()` tasks are send\nto the server in order to complete the initialization.\n\n* **Initialization task**\n\nTask that runs once during initialization and can be used to set up the\nserver. The return value of this function must be a dict, which is then\npassed to the :code:`exec_task` function with every request by a client.\n\n.. code-block:: python\n    \n    def init_task(client_socket: ClientSocket) -\u003e dict:\n        init_args = {\"request_count\": 0, \"value\": 1000}\n        return init_args\n\n* **Execution task**\n\nTask that is called each time a request is made by a client to the server.\nIn this task the message from the :code:`execute` method of the :code:`Client`\nclass is interpreted and an action has to be defined accordingly. The\ninput of the :code:`exec_task` is the return value of the last\n:code:`exec_task` function call (or if never called, the return value from the\n:code:`init_task`). Using the function :code:`respond` om the server, a second\nresponse can be sent to the client after the standard confirmation of the\nreceipt of the message by the server.\n\n.. code-block:: python\n    \n    def exec_task(\n        client_socket: ClientSocket, init_args: dict, exec_args: dict\n    ) -\u003e dict:\n        init_args[\"request_count\"] += 1\n        if exec_args[\"command\"] == \"increase\":\n                init_args[\"value\"] += exec_args[\"value_change\"]\n        if exec_args[\"command\"] == \"decrease\":\n                init_args[\"value\"] -= exec_args[\"value_change\"]\n        return init_args\n\n* **Exit task**\n\nTask that is executed once if an exit message is sent to the server by\nthe :code:`terminate` method of the :code:`Client` class. The input of the\n:code:`exit_task` is the return value of the last :code:`exec_task` function\ncall (or if never called, the return value from the :code:`init_task`). With\n:code:`respond` a second message can be sent to the client, if the client is\nset to be waiting for a second response\n(:code:`Client.terminate(..., await_response=True`).\n\n.. code-block:: python\n    \n    def exit_task(\n        client_socket: ClientSocket, init_args: dict, exit_args: dict\n    ) -\u003e None:\n        init_args[\"request_count\"] += 1\n        init_args[\"status\"] = \"Exited.\"\n        respond(client_socket, init_args)\n        return None\n\n**Note:** If the client is set to wait for a second response\n(:code:`Client.execute(..., await_response=True` or\n:code:`Client.terminate(..., await_response=True`) it is important to handle\nthis on the server side by sending a response to the client using\n:code:`respond`. Otherwise the client may be waiting forever as there is no\ntimeout specified.\n\n\nRun the server\n^^^^^^^^^^^^^^\n\nRun an example background process on localhost and send requests using client\nsockets:\n\n.. code-block:: python\n\n    from bgpy import Client, Server\n    from bgpy.example.tasks import init_task, exec_task, exit_task\n\n    HOST = \"127.0.0.1\"\n    PORT = 54321\n\n    # Optionally set a token for the client authentication\n    from bgpy import token_create\n    TOKEN = token_create()\n\n    # Create server context\n    server = Server(host=HOST, port=PORT, token=TOKEN)\n\n    # Start server in background from context\n    server.run_background()\n\n    # Bind client to server context\n    client = Client(host=HOST, port=PORT, token=TOKEN)\n\n    # Send INIT message from client to server, receive OK\n    response = client.initialize(init_task, exec_task, exit_task)\n\n    # Execute command 'increase' with value on server, receive OK\n    response = client.execute({\"command\": \"increase\", \"value_change\": 10})\n\n    # Execute command 'decrease' with value on server, receive OK\n    response = client.execute({\"command\": \"decrease\", \"value_change\": 100})\n\n    # Terminate and wait for response, receive OK with values\n    response = client.terminate(await_response=True)\n\nLicense\n-------\n\nThis project is licensed under the MIT License - see the LICENSE file for\ndetails.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmunterfi%2Fbgpy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmunterfi%2Fbgpy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmunterfi%2Fbgpy/lists"}