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').