DEV Community

Cover image for Turn Any Python Function into a GUI
Likianta D
Likianta D

Posted on

Turn Any Python Function into a GUI

Turn Any Python Function into a GUI

What if you could get a GUI without writing GUI code?

The community already has two well-known answers: PyGUIAdapter and Gooey.

  • PyGUIAdapter

  • Gooey

And when a terminal UI is enough, Trogon is a library I personally like a lot.

Now there is a new challenger: ArgSense.

So what is different?

ArgSense is a command line argument parser at heart. The GUI is a recent, optional layer on top of it. The pitch:

  • Your function does not change. ArgSense reads its signature and annotations and builds the interface from them: every parameter becomes a widget.
  • It stays light. Compared with Gooey, the UI is a motorcycle next to a car: fewer knobs, much less to learn.
  • It can produce a desktop launcher. A double-clickable .exe or .lnk, with an icon of your own.
  • The launcher is tiny. A .lnk is 1–2 KB; an .exe is about 1.2 MB. It does not bundle a Python runtime — it starts the venv you already have. A PyInstaller or PySide build of the same script weighs tens or hundreds of megabytes.
  • It does not build on argparse. The parser is ArgSense's own, and that is the library's main business.

    Before (argparse + gooey):

    from gooey import Gooey, GooeyParser
    
    @Gooey(program_name='Image Resizer')
    def main():
        parser = GooeyParser(description='Resize images in a folder.')
        parser.add_argument(
            'src', metavar='Source folder', widget='DirChooser'
        )
        parser.add_argument(
            '--width', type=int, default=800, metavar='Target width'
        )
        parser.add_argument(
            '--overwrite',
            action='store_true',
            metavar='Overwrite originals',
        )
        args = parser.parse_args()
        print(args)
    
    if __name__ == '__main__':
        main()
    

    After (argsense):

    from argsense import cli
    
    def resize(src: str, width: int = 800, overwrite: bool = False):
        """
        Resize images in a folder.
    
        params:
            src: the folder of images.
            width: the target width in pixels.
            overwrite: replace the originals instead of writing copies.
        """
        print(f'resizing {src} to {width}px ...')
    
    if __name__ == '__main__':
        # python main.py :gui
        cli.run(resize)
    
  • No PySide, PyQt or wxPython. The form is rendered by streamlit-canary, and the native window is opened by pyapp-window.

Install

pip install argsense[all]
Enter fullscreen mode Exit fullscreen mode

That installs ArgSense plus what the GUI needs: pillow (to turn a PNG icon into an ICO), streamlit-canary (the form), pyapp-window (the window), and a few more.

One more thing, if you want the desktop launcher: two binaries are deliberately not shipped in the wheel.

python -m argsense pull-launcher-misc
Enter fullscreen mode Exit fullscreen mode

It fetches rcedit.exe (~1.3 MB) and stub.exe (~1.2 MB)1 from the repository's misc folder into <argsense>/launcher/assets/.

Use

One function

# main.py
from argsense import cli


def resize(src: str, width: int = 800, overwrite: bool = False):
    """
    Resize images in a folder.

    params:
        src: the folder of images.
        width: the target width in pixels.
        overwrite: replace the originals instead of writing copies.
    """
    print(f'resizing {src} to {width}px (overwrite={overwrite})')


if __name__ == '__main__':
    cli.run(resize)
Enter fullscreen mode Exit fullscreen mode

First of all it is a command line tool:

python main.py --help
python main.py ./photos --width 1280
Enter fullscreen mode Exit fullscreen mode

Append :gui, and the same function becomes a window:

python main.py :gui     # a native window
python main.py :guiw    # a browser tab (w = windowless, like "pythonw")
python main.py ./photos --width 1280 :gui  # prefill args into components
Enter fullscreen mode Exit fullscreen mode

A desktop launcher

python -m argsense create_launcher
Enter fullscreen mode Exit fullscreen mode


python -m argsense create_launcher main.py "Image Resizer" -a "./photos --width 1280"
Enter fullscreen mode Exit fullscreen mode
  • The output goes to the desktop by default: Image Resizer.exe when the toolchain is in place, otherwise Image Resizer.lnk. Pass -o <dir> to write it elsewhere; a shortcut is then left on the desktop.
  • -a bakes arguments into the launcher, so the form is prefilled on double-click.
  • -i logo.png sets the icon for both the launcher and the window (a PNG is converted to a multi-size ICO).
  • -t / -z set the window title and size; -p pins the port (the default is a free port, picked at every start).
  • -c keeps a console window around, for debugging.
  • A module works as well: create_launcher myapp.main -n MyApp is the equivalent of python -m myapp.main :gui.

One caveat: the launcher does not bundle a Python runtime. It records the interpreter of the venv you built it from, which makes it perfect for your own machine and useless on a machine without your environment.

Who is it for

  • Tools you build for yourself, where remembering a dozen flags is the annoying part.
  • Command line scripts with a lot of parameters.
  • Machines where you set the environment up but the person using it does not live in a terminal — hand them a desktop launcher instead.

Not for: polished desktop apps that need custom widgets and hand-made layouts. Those still belong to Qt, or to a web front end.

Try it

pip install argsense[all]
python -m argsense pull-launcher-misc
python -m argsense welcome gui
Enter fullscreen mode Exit fullscreen mode

welcome also takes cli and tui, if you want to see the other two faces of the same demo.

If you have ever put off building an interface for a script, try :gui first — it costs one token.


  1. If GitHub is slow or blocked where you are, use the mirror: python -m argsense pull-launcher-misc --mirror-site. ↩

Top comments (0)