# Can't use \`launchConsoleProcess\`

**URL:** <https://discourse.slicer.org/t/cant-use-launchconsoleprocess/24414>\
**Category:** Development\
**Created:** [July 20, 2022, 4:33pm UTC](https://discourse.slicer.org/t/cant-use-launchconsoleprocess/24414 "2022-07-20T16:33:37Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![keri](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/keri/32/11618_2.png) [@keri](https://discourse.slicer.org/u/keri)\
**Post date:** [July 20, 2022, 4:33pm UTC](https://discourse.slicer.org/t/cant-use-launchconsoleprocess/24414/1 "2022-07-20T16:33:37Z")

</div>

Hi,

From this [topic](https://discourse.slicer.org/t/calling-slicer-module-from-a-python-file/12720) I’m trying to run simple command and see output in Slicer Log messages:

```python
slicer.util.launchConsoleProcess([sys.executable, '-c', 'print(\"Hi\")'])

```

I get the output in Python console `<Popen: returncode: None args: ['C:/C/r/python-install/bin/PythonSlicer.exe'...>`

But I hoped to see `Hi` in Log Messages.

Maybe I misunderstand something?

---

<div class="post-metadata">

**Author:** ![keri](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/keri/32/11618_2.png) [@keri](https://discourse.slicer.org/u/keri)\
**Post date:** [July 20, 2022, 5:01pm UTC](https://discourse.slicer.org/t/cant-use-launchconsoleprocess/24414/2 "2022-07-20T17:01:28Z")

</div>

Of it seems I needed to read data from returned `Popen`:

```python
p = slicer.util.launchConsoleProcess([sys.executable, '-c', 'print(\"Hi\")'])
print(p.stdout.read())

```

But is there a way to run subprocess with stdout to Slicer Log message?  
Something similar to:

```python
subprocess.run(my_cmd, stdout=slicer.stdout)

```

---

<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:** [July 20, 2022, 5:35pm UTC](https://discourse.slicer.org/t/cant-use-launchconsoleprocess/24414/3 "2022-07-20T17:35:30Z")

</div>

`slicer.util.launchConsoleProcess` is typically used with [`slicer.util.logProcessOutput`](https://slicer.readthedocs.io/en/latest/developer_guide/slicer.html#slicer.util.logProcessOutput) to wait for the execution to complete and forward the process output to the application log.

---

<div class="post-metadata">

**Author:** ![keri](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/keri/32/11618_2.png) [@keri](https://discourse.slicer.org/u/keri)\
**Post date:** [July 20, 2022, 5:56pm UTC](https://discourse.slicer.org/t/cant-use-launchconsoleprocess/24414/4 "2022-07-20T17:56:06Z")

</div>

Thank you,

Is there a way to do such thing on the background i.e. without stopping Slicer?

I’ve seen [similar topic](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/3) and does @pieper 's solution with [SlicerProcesses extension](https://github.com/pieper/SlicerParallelProcessing) is able to help me? I’m going to execute heavy computation that may take long time and it would be pretty attractive to run it on the background and to see all output somwhere in Slicer GUI.  
Haven’t tested SlicerParallelProcessing yet.

And the latest option probably is python cli module, but it scares me a little as it claims to write GUI in XML 🙂

---

<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:** [July 20, 2022, 7:27pm UTC](https://discourse.slicer.org/t/cant-use-launchconsoleprocess/24414/5 "2022-07-20T19:27:27Z")

</div>

If you only need to run one long processing at a time then you can use the CLI infrastructure (either calling C++ or Python CLI modules). If you start multiple CLI modules then they are executed one after the other, so if you want to run several of them in parallel then you would need to improve the CLI infrastructure or use another mechanism.

SlicerProcesses manages many long-running tasks in parallel, so you can use this for managing your background processes.

You can manage processes manually, too - launching them using `launchConsoleProcess` and monitor their status, gather output from them using customized versions of `logProcessOutput` (see for example in [SlicerElastix](https://github.com/lassoan/SlicerElastix/blob/3e9ef490ee6a6f901daa3280af112950f6af13ec/Elastix/Elastix.py#L708-L739)).

Probably SlicerProcesses would be the best solution for your needs.

---

<div class="post-metadata">

**Author:** ![keri](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/keri/32/11618_2.png) [@keri](https://discourse.slicer.org/u/keri)\
**Post date:** [July 20, 2022, 10:11pm UTC](https://discourse.slicer.org/t/cant-use-launchconsoleprocess/24414/6 "2022-07-20T22:11:57Z")

</div>

Is it ok to run threads in python within Slicer?  
For example create python module and create thread:

```python
  def threaded_function(self, arg):
    from time import sleep
    for i in range(arg):
      print("running")
      sleep(1)

  thread = Thread(target = self.threaded_function, args = (10, ))
  thread.start()

```

from a first glance it works: the text “running” appears with some time step (definately not 1 second but still) and I’m able to use Slicer while it is executing.

---

<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:** [July 20, 2022, 10:25pm UTC](https://discourse.slicer.org/t/cant-use-launchconsoleprocess/24414/7 "2022-07-20T22:25:25Z")

</div>

I would only use threads for very short, very frequent operations (where launching a separate process would be a significant overhear) or that needs complex interaction with the scene or when operating on extremely large data (that would cause significant extra memory usage to copy into another thread). For most other cases, launching a separate process for background processing is preferable, because it is:

- interruptible (you cannot force a thread to stop from the same process, but you can always terminate a separate process)
- safer (if an algorithm crashes in a subprocess then it won’t crash the main application, but if an algorithm crashes in a background thread of the main application then it will make the main application crash)
- more versatile (you can run any binary, you can run code in a different virtual Python environment, etc.)

---

<div class="post-metadata">

**Author:** ![keri](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/keri/32/11618_2.png) [@keri](https://discourse.slicer.org/u/keri)\
**Post date:** [July 20, 2022, 10:33pm UTC](https://discourse.slicer.org/t/cant-use-launchconsoleprocess/24414/8 "2022-07-20T22:33:15Z")

</div>

That makes sense.  
Thank you for sharing these ideas, haven’t thought about it.

---

<div class="post-metadata">

**Author:** ![keri](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/keri/32/11618_2.png) [@keri](https://discourse.slicer.org/u/keri)\
**Post date:** [July 21, 2022, 12:49pm UTC](https://discourse.slicer.org/t/cant-use-launchconsoleprocess/24414/9 "2022-07-21T12:49:10Z")

</div>

It seems I’ve found a curious solution to the issue - [QProcess](https://doc.qt.io/qt-6/qprocess.html).  
Advantages: usability of signals/slots when new data is available on the stream, when finished etc.

```python
# somwhere in setup
self.qprocess = qt.QProcess()
# without `qt.QProcess.MergedChannels` onProcessReadyReadStandardOutput called only once at the end of the subprocess execution
self.qprocess.setProcessChannelMode(qt.QProcess.MergedChannels)
self.qprocess.connect('readyReadStandardOutput()', self.onProcessReadyReadStandardOutput)
self.qprocess.connect('errorOccurred(qt.QProcess.ProcessError)', self.onProcessErrorOccured)
self.qprocess.connect('finished(int)', self.onProcessFinished)

#.........................................................................

# slots
def onProcessReadyReadStandardOutput(self):
  print("QProcess output:\t", str(self.qprocess.readAllStandardOutput()))

def onProcessErrorOccured(self, err : qt.QProcess.ProcessError):
  print("QProcess error:\t", str(err))

def onProcessFinished(self, exitCode : int):
  print("QProcess finished:\t", str(exitCode))

def onStartButtonClicked(self):
  self.qprocess.setProgram('C:\\my.exe')
  self.qprocess.setArguments(['-E', 'my_command'])
  self.qprocess.start() # or startDetached(): as I understood even if app is closed detached process will still be running
  # the code goes further without stopping execution

```

This doesn’t block Slicer or python and output appears in the console as it becomes ready.

Are there any disadvantages?

Few links that helped me:

> **[Get output stream from QProcess](https://forum.qt.io/topic/108032/get-output-stream-from-qprocess)**
>
> Hello, this is my code: QProcess process; process.start("sudo apt update"); process.waitForFinished(-1); QString stdout = process.readAllStandardOutput(); QString stderr = process.readAllStandardError(); I have 3 questions: How...

> **[QProcess::readAll and QProcess::readAllStandardOutput both return an empty...](https://forum.qt.io/topic/75454/qprocess-readall-and-qprocess-readallstandardoutput-both-return-an-empty-string-after-qprocess-write-is-run/5)**
>
> Hi all note: this might become confusing, please bare with me! To get a basic sense of what I want to do: QProcess runs a command by QProcess::start("sh -c \\"cd /tmp/tempdir ; ./my\_script --option file.txt ; echo $?\\" ") The script expects input...

P.S. another option is to use `QTimer()` and send signals every say 10 seconds to do the updates (read output) but somewhere near each update (once in 10 seconds) the GUI may freeze for a half of a second (probably when signal is emitted)

---

<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:** [July 21, 2022, 6:24pm UTC](https://discourse.slicer.org/t/cant-use-launchconsoleprocess/24414/10 "2022-07-21T18:24:41Z")

</div>

Yes, a [SlicerParallelProcessing `Process` is a subclass of `QProcess`](https://github.com/pieper/SlicerParallelProcessing/blob/master/Processes/Processes.py#L206) so it has all the advantages of using signals and slots to integrate with the event loop of the app.

A `QTimer` could be helpful to give some progress information to the user, but yes, I’d suggest relying on the signals to determine when there is data ready to read so you don’t block.
