looking for a pattern to code logic shared by gui/cli

MRAB google at mrabarnett.plus.com
Thu Apr 16 22:07:02 CEST 2009


Andreas Balogh wrote:
> Only recently I have started developing code for application providing 
> both a GUI and a command line interface (CLI). Naturally I want to reuse 
> the business logic code for both GUI and CLI interfaces. The problem is 
> to provide feedback to the GUI on the one hand, to the CLI on the other 
> hand - by the same piece of code. My example shows a find_files() method 
> browsing through a directory tree. As this might take a while every 
> directory browsed shall be displayed on the terminal or in the GUI (an 
> optimisation is to display the current directory only once a second). 
> When a file fitting the criteria is found it is shown as well in both 
> terminal and GUI list widget.
> 
> I can easily write a piece of code for the CLI for that:
> 
>    import logging
>    import os
> 
>    LOG = logging.getLogger()
> 
>    def find_files(src_dir):
>        for root, dirs, files in os.walk(src_dir):
>            for file in files:
>                # feedback for the CLI
>                LOG.info("scanning %s %s", root, file)
>                # check for file pattern here
>                if os.path.exists(file2):
>                    # feedback for the CLI
>                    LOG.info("found %s", file2)
>                    # retrieve more file_details
>                    files.append((file, file_details))
>                else:
>                    LOG.warn("no file found for %s", file)
> 
> and for the GUI version:
> 
>    import Queue
>    import os
> 
>    class Model:
>        def __init__(self, model):
>            self.model = model
>            self.status_text = ""
> 
>        def notify()
>            "send message to Tk root widget to tell GUI thread to
>    synchronise view"
> 
>    def find_files(src_dir, model):
>        for root, dirs, files in os.walk(src_dir):
>            for file in files:
>                # feedback for the GUI
>                model.status_text = "scanning %s %s" % (root, file)
>                model.notify()
>                # check for file pattern here
>                if os.path.exists(file2):
>                    # feedback for the GUI
>                    # retrieve more file_details
>                    model.files.append((file, file_details))
>                    model.notify()
>                else:
>                    pass
> 
> Now I have duplicated the "business logic" of find_files() for a GUI 
> driven application and a CLI application. Using the same code is easy as 
> long as no feedback is required during operation. But in this case the 
> os.walk() might scan an entire disk taking a minute or two. Here both 
> the terminal or the GUI need to provide feedback about the directories 
> being scanned or the user might think the application has died (I would 
> certainly).
> 
> Solutions with callbacks seem kind of ugly to me as they require "model" 
> to be passed through for GUI and LOG for the CLI version.
> 
> Does a good (pythonic) pattern exist to solve this in a better way?
> 
> Note: sorry, the code sample will not run on its own. I thought it'd be 
> to lengthy to have a functioning sample, especially for the gui.
> 
You could pass a notification object into the function. There would be a
CLINotification class and a GUINotification class, both having methods
for reporting status info ('report_status') and adding files
('add_files').



More information about the Python-list mailing list