By utilizing WRY, PyWry uses the built-in browsers specific to each system: WebKit for macOS, WebView2 for Windows, and WebKitGTK for Linux. This clever approach enables PyWry to maintain a remarkably small footprint of approximately 2MB for both Mac and Windows platforms. However, Linux users may need to install a few additional libraries to ensure compatibility.
We're staying true to our Open Source roots by offering this up for everyone to use and contribute too - check the bottom of the article for a link to the repository.
PyWry takes a different approach than other HTML/GUI/Image viewers that exist for Python:
- Bokeh, Altair, bqplot, and ipyvolume rely on the Selenium to perform image rendering.
- Orca, which uses a headless Electron application that uses the Chromium browser engine built into Electron.
- Kaleido, which runs its own build of Chromium as a library.
✅ - available 🚩 - requires custom code ⛔ - N/A
Beyond serving as an HTML viewer, PyWry offers additional functionalities. Users can take advantage of PyWry's capability to export images, allowing them to save rendered web content as image files. Moreover, PyWry provides the ability to access and manipulate the Document Object Model (DOM), empowering developers to extract and work with structured data from the rendered web page.
Why we made it
PyWry was built partly out of frustration and mostly out of love for Rust and Python. We wanted to create a tool that could be used to display web views from our pure Python program – OpenBB Terminal, but it had to be lightweight and open source.
What it does
PyWry has quite a few uses, and I'm sure many more could be added as well.
Currently, in its simplest implementation, PyWry allows sending HTML to a WebView.
import asyncio import sys from pywry import PyWry async def main_loop(): while True: await asyncio.sleep(1) if __name__ == "__main__": try: handler = PyWry() handler.send_html( html="<h1 style='color: red;'>Welcome to PyWry!</h1>", title="PyWry Demo", ) handler.start() # PyWry creates a new thread for the backend, # so we need to run the main loop in the main thread. # otherwise, the program will exit immediately. handler.loop.run_until_complete(main_loop()) except KeyboardInterrupt: print("Keyboard interrupt detected. Exiting...") sys.exit(0)
We also have more advanced examples for sending Plotly Figures and exporting, using Streamlit, and sending an HTML file.
Additionally, here are some other features we are working on:
- Drop-in replacement for Kaleido – used by Plotly to render figures to an image. In our early testing, we saw a 20-40% speed improvement over Kaleido.
- Web Scraping – Using this as another way to export the DOM from a WebView.
And of course, we are open to any other features you can dream of. 😊