A
Andreas Balogh
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.
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.