# Printing in Python CLI modules

**URL:** <https://discourse.slicer.org/t/printing-in-python-cli-modules/29516>\
**Category:** Development\
**Created:** [May 17, 2023, 4:53pm UTC](https://discourse.slicer.org/t/printing-in-python-cli-modules/29516 "2023-05-17T16:53:25Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![benzwick](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/benzwick/32/80521_2.png) [@benzwick](https://discourse.slicer.org/u/benzwick)\
**Post date:** [May 17, 2023, 4:53pm UTC](https://discourse.slicer.org/t/printing-in-python-cli-modules/29516/1 "2023-05-17T16:53:25Z")

</div>

When I print in a Python CLI module, all the messages are displayed after the module has completed. Is there any way to print the messages as they occur in real time during execution?

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [May 17, 2023, 5:08pm UTC](https://discourse.slicer.org/t/printing-in-python-cli-modules/29516/2 "2023-05-17T17:08:56Z")

</div>

Python CLI (like C++ CLI) modules are very special purpose. If they don’t suit your needs you are much better off writing a scripted module, or wrapping your CLI in a more general purpose script.

---

<div class="post-metadata">

**Author:** ![benzwick](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/benzwick/32/80521_2.png) [@benzwick](https://discourse.slicer.org/u/benzwick)\
**Post date:** [May 17, 2023, 5:30pm UTC](https://discourse.slicer.org/t/printing-in-python-cli-modules/29516/3 "2023-05-17T17:30:03Z")

</div>

I’m developing an [extension](https://github.com/SlicerCBM/SlicerFreeSurferCommands) to run some FreeSurfer commands inside Slicer. Python CLI modules seem perfect because all I need is a GUI for running existing external commands. So far I have the SynthStrip command implemented and it works very well. The only issue is there is no way to know what is happening while the module is running, which for some commands might take several minutes or longer. As far as I understand, a scripted module would [block the GUI](https://discourse.slicer.org/t/basic-questions-on-cli-modules-vs-scripted-modules/10782/2), which would not be a good trade-off I think.

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [May 17, 2023, 5:46pm UTC](https://discourse.slicer.org/t/printing-in-python-cli-modules/29516/4 "2023-05-17T17:46:07Z")

</div>

Right, it makes sense to run these as separate processes, but they don’t need to use the CLI infrastructure, which is really designed to be used for very simple use cases where autogenerating the GUI was preferred. Basically the original motivation for C++ CLIs was to easily port a bunch of ITK example programs for use in Slicer.

Instead you can launch and manage processes using python, most cleanly with the QProcess inftrastructure, that gives you a clean cross platform signals-and-slots based interface for managing IO. You may want to build on [the ParallelProcessing extension](https://github.com/pieper/SlicerParallelProcessing/blob/master/Processes/Processes.py) or just learn from how it use QProcess. The same approach is [used in the DICOM module](https://github.com/Slicer/Slicer/blob/main/Modules/Scripted/DICOMLib/DICOMProcesses.py).

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [May 17, 2023, 6:15pm UTC](https://discourse.slicer.org/t/printing-in-python-cli-modules/29516/5 "2023-05-17T18:15:03Z")

</div>

> [@benzwick](#):
>
> The only issue is there is no way to know what is happening while the module is running

If the process provides some output then you can capture that and print to the output using XML tags described [here](https://www.slicer.org/wiki/Documentation/Nightly/Developers/SlicerExecutionModel#Showing_Progress_in_an_Application).

See for example in ModelMaker CLI module:

> [@benzwick](#):
>
> As far as I understand, a scripted module would [block the GUI](https://discourse.slicer.org/t/basic-questions-on-cli-modules-vs-scripted-modules/10782/2), which would not be a good trade-off I think.

You don’t have to block the GUI, especially if work is done in a different process. I find that most often I block the GUI (just leave a `Cancel` button enabled to allow cancelling the operation) because it makes things a bit simpler. But if you want the user to be able to continue using Slicer then you can use the CLI infrastructure to run executables, or as @pieper sugested use Qt classes (and to get notified about process via signals/slots); or use Python functions (and use QTimer to check the process state and outputs).

---

<div class="post-metadata">

**Author:** ![benzwick](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/benzwick/32/80521_2.png) [@benzwick](https://discourse.slicer.org/u/benzwick)\
**Post date:** [May 19, 2023, 6:15am UTC](https://discourse.slicer.org/t/printing-in-python-cli-modules/29516/6 "2023-05-19T06:15:41Z")

</div>

Thanks for the advice. I’ll try rewriting the extension using scripted modules.
