{"id":16277470,"url":"https://github.com/maximilian-winter/pytonium","last_synced_at":"2026-02-28T06:09:25.778Z","repository":{"id":137933834,"uuid":"559938991","full_name":"Maximilian-Winter/pytonium","owner":"Maximilian-Winter","description":"This is a framework for building python apps, with a GUI based on the web technologies HTML, CSS and Javascript. Powered by Chromium Embedded Framework.","archived":false,"fork":false,"pushed_at":"2023-10-01T11:13:16.000Z","size":34836,"stargazers_count":46,"open_issues_count":1,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-12-28T08:30:34.554Z","etag":null,"topics":["chromium","cython","cython-wrapper","python"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Maximilian-Winter.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-31T12:20:17.000Z","updated_at":"2024-11-27T12:03:40.000Z","dependencies_parsed_at":"2024-10-27T10:51:14.205Z","dependency_job_id":"bd3b9bc3-8186-4491-b8d9-0e529392e474","html_url":"https://github.com/Maximilian-Winter/pytonium","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Maximilian-Winter%2Fpytonium","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Maximilian-Winter%2Fpytonium/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Maximilian-Winter%2Fpytonium/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Maximilian-Winter%2Fpytonium/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Maximilian-Winter","download_url":"https://codeload.github.com/Maximilian-Winter/pytonium/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":233426087,"owners_count":18674549,"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":["chromium","cython","cython-wrapper","python"],"created_at":"2024-10-10T18:54:52.378Z","updated_at":"2025-09-17T21:32:44.733Z","avatar_url":"https://github.com/Maximilian-Winter.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Pytonium\n### Pytonium is a framework for building python apps, with a GUI based on the web-technologies HTML, CSS and Javascript.\n\nIt uses the Chromium Embedded Framework for rendering and execution of javascript.\n\n### Features:\n\n- Create appealing UIs for Python Apps through the web-technologies HTML, CSS and Javascript, using frameworks like React, Preact and Tailwind CSS for styling.\n- Call Python function and methods from Javascript and return values from Python to Javascript.\n- Handle the application state through simple methods and event based interfaces in Javascript and Python.\n- Execute Javascript from Python on the UI.\n\nThe package is available via pip.\n\nSo just type the following in the console to install it.\n```\npip install Pytonium\n```\n## Getting Started\nTo start Pytonium and load a website or local site, you have to first import Pytonium\n\n```python\nfrom Pytonium import Pytonium\n```\nThis imports the Pytonium class.\n\nAfter we have created an instance of Pytonium, we can initialize Pytonium, with an initial window width and height and\na URL or filepath.\n\n```python\nfrom Pytonium import Pytonium\n\npytonium = Pytonium()\npytonium.initialize(\"C:\\TestSite\\index.html\", 1920, 1080)\n```\nNow the App starts the browser on the URL or filepath, we provided.\n\nAfter the initialization, we need to call the method \"update_message_loop\" on the Pytonium instance. We need to do\nthis in a regular interval, so the chromium embedded framework can update.\nThe easiest way to do this, is with a while loop, that runs as long the browser is open.\n\n```python\nimport time\nfrom Pytonium import Pytonium\n\npytonium = Pytonium()\n\npytonium.initialize(\"C:\\TestSite\\index.html\", 1920, 1080)\n\nwhile pytonium.is_running():\n    time.sleep(0.01)\n    pytonium.update_message_loop()\n```\n\nThis are the basics to load an HTML file, with CSS and Javascript.\n\n## JavaScript and Python Interoperability\n\n### Binding Python Functions\n\nWe have the option to register python functions and methods in Javascript. And make them callable from there.\n\n```python\nimport time\nfrom Pytonium import Pytonium\n\npytonium = Pytonium()\n\n# This function is the endpoint of a javascript binding, and it's get called on the test website and returns an object to Javascript.\n@returns_value_to_javascript(\"any\")\ndef my_js_binding():\n    return {\"Answer\": 42}\n\n# Bind the test function to javascript, we have to provide a name under which the function will be found and the actual function, we can pass an optional object name in Javascript.\npytonium.bind_function_to_javascript(my_js_binding, \"testfunc\", \"test_function_binding\")\n\n\npytonium.initialize(\"C:\\TestSite\\index.html\", 1920, 1080)\n\nwhile pytonium.is_running():\n    time.sleep(0.01)\n    pytonium.update_message_loop()\n```\n\nTo bind a Python function to Javascript, we have to provide a name under which the function will be found and the actual function, we can pass an optional object name in Javascript. After that we can call the function in Javascript like that:\n````javascript\nPytonium.test_function_binding.testfunc();\n````\n\nWe can also return values from Python to Javascript by using a Promise in Javascript, to get the return value of testfunc, we have to use a Promise returned by Pytonium like that:\n\n````javascript\n let myPromise = Pytonium.test_function_binding.testfunc();\nmyPromise.then((resolvedValue) =\u003e {\n    console.log(\"The answer to the Ultimate Question of Life, the Universe and Everything:\", resolvedValue.Answer);\n});\n````\nIt is possible to generate a typescript file of the Javascript bindings and other Pytonium functionality for IDE recognition and auto-completion. It is shown in following code example:\n\n```python\nimport time\nfrom Pytonium import Pytonium, returns_value_to_javascript\n\npytonium = Pytonium()\n\n# This function is the endpoint of a javascript binding, and it's get called on the test website and returns an object to Javascript.\n@returns_value_to_javascript(\"any\")\ndef my_js_binding():\n    return {\"Answer\": 42}\n\n# Bind the test function to javascript, we have to provide a name under which the function will be found and the actual function, we can pass an optional object name in Javascript.\npytonium.bind_function_to_javascript(my_js_binding, \"testfunc\", \"test_function_binding\")\n\npytonium.generate_typescript_definitions(\"test.d.ts\")\n\npytonium.initialize(\"C:\\TestSite\\index.html\", 1920, 1080)\n\nwhile pytonium.is_running():\n    time.sleep(0.01)\n    pytonium.update_message_loop()\n```\nThe following is the output of the example:\n\ntest.d.ts\n```typescript\ndeclare namespace Pytonium {\n    export namespace test_function_binding {\n        function testfunc(): any;\n    }\n    export namespace appState {\n        function registerForStateUpdates(eventName: string, namespaces: string[], getUpdatesFromJavascript: boolean, getUpdatesFromPytonium: boolean): void;\n        function setState(namespace: string, key: string, value: any): void;\n        function getState(namespace: string, key: string): any;\n        function removeState(namespace: string, key: string): void;\n    }\n}\ninterface Window {\n    PytoniumReady: boolean;\n}\ninterface WindowEventMap {\n    PytoniumReady: Event;\n}\n```\n## Managing Application State\n\n### JavaScript State Management\nWe also have the option to handle and manage the application state with the help of Pytonium. The application state is divided into namespaces, to add or set a namespace and value, we have to simply call 'setState' on the 'Pytonium.appState' object. The following code shows different ways to create and access a state or all states in a namespace:\n\n````javascript\n// Register to app state updates from Python and Javascript. You can pass a custom event name and a list of namespaces to subscribe to.\nPytonium.appState.registerForStateUpdates(\"ChangeDate\", [\"app-general\"], true, true);\n\n// Add a listener for the custom event and retrieve information.\ndocument.addEventListener('ChangeDate', function(event) {\n    const detail = event.detail;\n    const namespace = detail.namespace;\n    const key = detail.key;\n    const value = detail.value;\n\n    // console.log(\"State Updated:\", namespace, key, value);\n    document.getElementById('date').innerHTML = '\u003cp\u003e' + value + '\u003c/p\u003e';\n});\n\n// Set some app state, synced to Python and Javascript.\nPytonium.appState.setState(\"user\", \"age\", 64)\nconsole.log(Pytonium.appState.getState(\"user\", \"age\"));\n````\n\n### Python State Management\nTo get the updates to the state in Python, we have to implement a state handler, it basically looks like that in the simplest form:\n```python\n# An example class to handle app state updates from Javascript.\n# The update_state method is mandatory and gets called automatically from Pytonium.\nclass MyStateHandler:\n\n    def update_state(self, namespace, key, value):\n        print(f\"State Update:\\nNamespace={namespace}\\nKey={key}\\nValue={str(value)}\")\n\n# Create a MyStateHandler instance.\nmyStateHandler = MyStateHandler()\n# Add a state handler for the 'user' namespace and receive updates. 'user' is just an example used on the test website.\npytonium.add_state_handler(myStateHandler, [\"user\"])\n```\nThe only thing mandatory in a state handler is an update_state method with namespace, key and value as arguments. This method get called whenever a namespace changes a value to which the state handler is subscribed. In the example above is the state handler to the 'user' namespace subscribed.\n\n\n## Advanced Features\n\n### Custom protocol schemes\nTo load local files, you have to define a custom protocol scheme, like http/https.\nTo add a custom scheme, you can call 'add_custom_scheme' on the Pytonium object like that:\n```python\npytonium_test_path = os.path.abspath(__file__)\npytonium_test_path = os.path.dirname(pytonium_test_path)\n\n# The first argument is the protocol name, the second argument is the location on the disk, where the files are found.\npytonium.add_custom_scheme(\"pytonium\", f\"{pytonium_test_path}\\\\\")\npytonium.add_custom_scheme(\"pytonium-data\", f\"{pytonium_test_path}\\\\data\\\\\")\n```\nYou can then use the custom scheme in HTML, like that to load the files from the disk:\n```html\n\u003cscript src=\"pytonium://babylon.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"pytonium://babylonjs.loaders.js\"\u003e\u003c/script\u003e\n```\n\nYou can also map custom file endings to mime types, this is necessary for Pytonium to  load the files correctly!\nThe following code adds the mime type for glb 3D models to Pytonium.\n```python\npytonium.add_mime_type_mapping(\"glb\", \"model/gltf-binary\")\n```\nYou can find the complete example here: (https://github.com/Maximilian-Winter/pytonium_examples/blob/main/pytonium_example_babylon_js/main.py)\n\n### Context Menus\n\nYou can add custom context menus to your Pytonium application. The following code shows different ways to add context menus.\n\n```python\n# This class get later bind to the context menu of the Pytonium app.\nclass MyContextMenu:\n    def test_context_menu_one(self):\n        print(\"Hello Context Menu 1\")\n\n    def test_context_menu_two(self):\n        print(\"Hello Context Menu 2\")\n        # Here we change the context menu to another namespace, this allows multiple context menus, each under a different namespace.\n        pytonium.set_context_menu_namespace(\"test\")\n\ndef my_context_function():\n    print(\"Context menu clicked\")\n\n# The first argument is a Python function, the second and third argument are optional, the second one is display name for the context menu, the third the namespace or menu identifier.\npytonium.add_context_menu_entry(my_context_function, \"My Menu\")\n\nmyContextMenu = MyContextMenu()\n\npytonium.add_context_menu_entries_from_object(myContextMenu)\n```\n\n### Custom Window Icon\n\nSet a custom icon for your application window.\n\n```python\npytonium.set_custom_icon_path(\"path/to/icon.ico\")\n```\n\n---\n### Bindings, State and Context Menus\nThe bindings of the Python functions and methods, the context menus, and state handlers, has to be performed before Pytonium is initialized and started.\nYou can also bind complete Python objects with all its methods to Javascript, which is show in the complete example below:\n---\n\n### Complete example:\nThe following is the Python code, the corresponding HTML and Javascript code is below.\n```python\nimport os\nimport time\nfrom datetime import datetime\n\n# Import the Pytonium class\nfrom Pytonium import Pytonium, returns_value_to_javascript\n\n\n# This class expose two methods as an endpoint of a javascript binding, and they get called on the test website.\n# The first method gets called with one argument and returns a value.\nclass MyApi:\n\n    def __init__(self):\n        self.data = []\n\n    # Needed decorator to mark the method as returning values as Promises in Javascript, optional with return type in Javascript to generate typescript d.ts file of all exposed Python methods and functions.\n    @returns_value_to_javascript(\"number\")\n    def test_one(self, arg1: int):\n        print(\"Python Method called from Javascript with one argument and returns a value!\")\n        print(arg1)\n        return arg1\n\n    def test_two(self, arg1: str, arg2: int, arg3: int):\n        print(\"Python Method called from Javascript!\")\n        self.data.append(arg1)\n        self.data.append(arg2)\n        self.data.append(arg3)\n        print(self.data)\n\n# This class get later bind to the context menu of the Pytonium app.\nclass MyContextMenu:\n    def test_context_menu_one(self):\n        print(\"Hello Context Menu 1\")\n\n    def test_context_menu_two(self):\n        print(\"Hello Context Menu 2\")\n        # Here we change the context menu to another namespace, this allows multiple context menus, each under a different namespace.\n        pytonium.set_context_menu_namespace(\"test\")\n\n\n# An example class to handle app state updates from Javascript.\n# The update_state method is mandatory and gets called automatically from Pytonium.\nclass MyStateHandler:\n\n    def update_state(self, namespace, key, value):\n        print(f\"State Update:\\nNamespace={namespace}\\nKey={key}\\nValue={str(value)}\")\n\n\n# Create a Pytonium instance.\npytonium = Pytonium()\n\n# Create a MyApi instance.\nmyApi = MyApi()\nmyContextMenu = MyContextMenu()\n\n# Create a MyStateHandler instance.\nmyStateHandler = MyStateHandler()\n\n\n# This function is the endpoint of a javascript binding, and it's get called on the test website and returns a Javascript object.\n@returns_value_to_javascript(\"any\")\ndef testfunc():\n    return {\"Answer\": 42}\n\n\n# This function gets later bind to the context menu.\ndef test_context_menu_three():\n    print(\"Hello Context Menu 3\")\n\n\n# This function also gets later bind to the context menu.\ndef test_context_menu_four():\n    print(\"Hello Context Menu 4\")\n\n\n# Add a state handler for the 'user' namespace and receive updates. 'user' is just an example used on the test website.\npytonium.add_state_handler(myStateHandler, [\"user\"])\n\n# Bind the MyApi instance and the test function to javascript.\npytonium.bind_function_to_javascript(testfunc, javascript_object=\"test_function_binding\")\npytonium.bind_object_methods_to_javascript(myApi, javascript_object=\"test_class_methods_binding\")\n\n# Bind the different context menus to the Pytonium app.\npytonium.add_context_menu_entries_from_object(myContextMenu)\npytonium.add_context_menu_entry(test_context_menu_three, \"Test Context Menu 3!\", \"test\")\npytonium.add_context_menu_entry(test_context_menu_four, \"Test Context Menu 4!\", \"test\")\n\n# Generate a typescript d.ts file, of the Python bindings, for the IDE to support auto-completetion etc.\npytonium.generate_typescript_definitions(\"test.d.ts\")\n\n# To load a html file, on start up from disk, we need the absolute path to it, so we get it here.\npytonium_test_path = os.path.abspath(__file__)\npytonium_test_path = os.path.dirname(pytonium_test_path)\n\n# Set a custom icon for the window.\npytonium.set_custom_icon_path(f\"radioactive.ico\")\n\n# Start Pytonium and pass it the start-up URL or file and the width and height of the Window.\npytonium.initialize(f\"file://{pytonium_test_path}\\\\index.html\", 1920, 1080)\n\n# Start a loop to update the Pytonium message loop and execute some javascript.\nwhile pytonium.is_running():\n    time.sleep(0.01)\n\n    # Update the message loop.\n    pytonium.update_message_loop()\n\n    # Get the current time and date for displaying it on the test website.\n    now = datetime.now()\n\n    # Format the date and time string.\n    date_time = now.strftime(\"%d.%m.%Y, %H:%M:%S\")\n\n    # Set an app state to a specific value.\n    pytonium.set_state(\"app-general\", \"date\", date_time)\n\n    # Example on how to execute Javascript from Python:\n\n    # Save the needed Javascript, to call a function and update a ticker with the current date and time.\n    # We created and exposed this function in Javascript on the HTML site.\n    # code = f\"CallFromPythonExample.setTicker('{date_time}')\"\n\n    # Execute the javascript.\n    # pytonium.execute_javascript(code)\n\n```\nHere is the corresponding HTML and Javascript code.\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n    \u003cmeta charset=\"UTF-8\"\u003e\n    \u003ctitle\u003ePytoniumTest\u003c/title\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n\u003cdiv id =\"app\"\u003e\n    \u003cp\u003eHello World!\u003c/p\u003e\n    \u003cdiv id =\"date\"\u003e\n\n    \u003c/div\u003e\n\u003c/div\u003e\n\n\u003c/body\u003e\n\u003cscript\u003e\n\n    // Define a function to showcase Pytonium features.\n    function CallToPythonExample()\n    {\n        // Register to app state updates from Python and Javascript. You can pass a custom event name and a list of namespaces to subscribe to.\n        Pytonium.appState.registerForStateUpdates(\"ChangeDate\", [\"app-general\"], true, true);\n\n        // Add a listener for the custom event and retrieve information.\n        document.addEventListener('ChangeDate', function(event) {\n            const detail = event.detail;\n            const namespace = detail.namespace;\n            const key = detail.key;\n            const value = detail.value;\n\n            // console.log(\"State Updated:\", namespace, key, value);\n            document.getElementById('date').innerHTML = '\u003cp\u003e' + value + '\u003c/p\u003e';\n        });\n\n        // Set some app state, synced to Python and Javascript.\n        Pytonium.appState.setState(\"user\", \"age\", 64)\n        console.log(Pytonium.appState.getState(\"user\", \"age\"));\n        // Call function in python with return value.\n        let myPromise = Pytonium.test_function_binding.testfunc();\n        myPromise.then((resolvedValue) =\u003e {\n            console.log(\"The answer to the Ultimate Question of Life, the Universe and Everything:\", resolvedValue.Answer);\n        });\n\n        console.log(Pytonium.appState.getState(\"user\", \"age\"));\n\n\n        let myPromise2 = Pytonium.test_class_methods_binding.test_one(64);\n        myPromise2.then((resolvedValue) =\u003e {\n            console.log(\"The answer to the Ultimate Question of Life, the Universe and Everything:\", resolvedValue);\n        });\n        Pytonium.test_class_methods_binding.test_two(\"Dlrow Olleh!\", 20, 40)\n    }\n\n    // Check if Python bindings are ready and call them, if not add an event listener for the PytoniumReady event.\n    if (window.PytoniumReady) {\n        CallToPythonExample();\n    } else {\n        window.addEventListener('PytoniumReady', function() {\n            CallToPythonExample();\n        });\n    }\n    // Example for defining a function that is callable from Python.\n    var CallFromPythonExample = {\n        setTicker: function(date) {\n            document.getElementById('app').innerHTML = '\u003cp\u003eHello World!\u003c/p\u003e' + '\u003cp\u003e' + date + '\u003c/p\u003e';\n        },\n    };\n\u003c/script\u003e\n\u003c/html\u003e\n```\nThe following is the generated typescript definition file:\n\ntest.d.ts\n```typescript\ndeclare namespace Pytonium {\n    export namespace test_function_binding {\n        function my_js_binding(): any;\n    }\n    export namespace test_class_methods_binding {\n        function test_one(arg1: number): number;\n        function test_two(arg1: string, arg2: number, arg3: number): void;\n    }\n    export namespace appState {\n        function registerForStateUpdates(eventName: string, namespaces: string[], getUpdatesFromJavascript: boolean, getUpdatesFromPytonium: boolean): void;\n        function setState(namespace: string, key: string, value: any): void;\n        function getState(namespace: string, key: string): any;\n        function removeState(namespace: string, key: string): void;\n    }\n}\ninterface Window {\n    PytoniumReady: boolean;\n}\ninterface WindowEventMap {\n    PytoniumReady: Event;\n}\n```\n\nYou can find more full examples here: (https://github.com/Maximilian-Winter/pytonium_examples)\n\nIt is tested and developed under Windows 11 and **Python 3.11**, but also has **Linux Support**. And can be used with **Python 3.10**.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaximilian-winter%2Fpytonium","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaximilian-winter%2Fpytonium","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaximilian-winter%2Fpytonium/lists"}