-1

I am currently working on a signal analyzing program with a GUI, which should run on Linux, OSX and Windows. For some reason this program won't run on Windows, but I don't get any Error Messages. More precisely my main program (GUI) fails to spawn my subprocess that should analyze the data and send the results to the GUI.

The only thing I found online was that Windows needs

if __name__ == '__main__':

to run processes correctly if they are created using the multiprocessing module. Sadly, adding this part didn't solve the problem for Qprocess.

I wrote a pretty simple script that has the same problem and communicates like my complex scripts.

Here my main GUI process:

import sys
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5 import uic
import pickle

class MyGuiApp(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.ui = uic.loadUi('process_gui.ui', self)

        
        # Set puchButtons
        self.stop_pB.setEnabled(False)
        self.start_pB.clicked.connect(self.start_measurement)
        self.stop_pB.clicked.connect(self.stop_measurement)

        # Initialising Subprocess
        self.my_process = QtCore.QProcess()
        self.my_process.readyReadStandardOutput.connect(self.new_data)

    def start_measurement(self):
        self.stop_pB.setEnabled(True)
        self.start_pB.setEnabled(False)

        self.my_process.start('python3', ['main_subprocess.py'])

    def stop_measurement(self):
        self.stop_pB.setEnabled(False)
        self.start_pB.setEnabled(True)

        self.my_process.terminate()

    def new_data(self):
        data = self.my_process.readAllStandardOutput()
        # unpickle data -> string
        stdout_str = pickle.loads(data)

        self.label.setText(stdout_str)


if __name__=='__main__':
    app = QtWidgets.QApplication(sys.argv)
    mainWindow = MyGuiApp()
    mainWindow.show()
    sys.exit(app.exec_())

'''

Here my Subprocess:

   import time
   import sys
   import pickle

   index = 0
   while True:
      start = time.time()

      sys.stdout.buffer.write(pickle.dumps(str(index)))
      sys.stdout.flush()

      index = index + 1
      time.sleep(0.5-(time.time()-start)) # sets loop runtime to 0.5 secs

And here the .ui file in case someone wants to run my code:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout_2">
    <item row="0" column="0">
     <widget class="QGroupBox" name="groupBox">
      <property name="title">
       <string>GroupBox</string>
      </property>
      <layout class="QGridLayout" name="gridLayout">
       <item row="0" column="0">
        <layout class="QVBoxLayout" name="verticalLayout">
         <item>
          <widget class="QPushButton" name="start_pB">
           <property name="text">
            <string>Start</string>
           </property>
          </widget>
         </item>
         <item>
          <widget class="QPushButton" name="stop_pB">
           <property name="text">
            <string>Stop</string>
           </property>
          </widget>
         </item>
         <item>
          <widget class="QLabel" name="label">
           <property name="font">
            <font>
             <pointsize>20</pointsize>
            </font>
           </property>
           <property name="text">
            <string>DATA</string>
           </property>
          </widget>
         </item>
        </layout>
       </item>
      </layout>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>22</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>
Dost
  • 1
  • 2
  • good work so far, but what exactly is the question please ? https://stackoverflow.com/help/minimal-reproducible-example – D.L Apr 15 '22 at 14:08
  • How do I need to change the code so that the subprocess spawns on a windows pc. As mentioned this code works fine on OSX and Linux but not windows. I don't know why as I don't get any Error Messages. – Dost Apr 15 '22 at 15:29
  • If one presses 'Start' in the GUI-window the subprocess should start and send a string. If on presses 'Start' on a windows Pc nothing the subprocess won't spawn but the rest of the GUI works fine. Closing the GUI will give Exit Code 0 just like everything work fine but it obviously didn't. – Dost Apr 15 '22 at 15:33
  • windows works differently to linux and ios. unless you have imported modules from subdirectories and other files should use the full path ie. c:\folder\filder\file.py – D.L Apr 16 '22 at 07:31
  • This didn't work either, I also tried giving the Qprocess a wrong path to see wether i get any Error Message but nothing happened. It seems like there is nothing happening at all. – Dost Apr 16 '22 at 08:44

2 Answers2

0

I run this in a windows 10 environment using the VS code editor.

I made no changes to the code whatsoever. I did this:

  1. I created the process_gui.ui file
  2. I created the main_subprocess.py file
  3. I replicted the code in the question

This works.

It produces this: enter image description here

And when i press the start button it initiates a counter like this:

enter image description here

So i can confirm that the code does run on windows. I hope that this helps you or at least confirms that it does run.

Given that the code works, you should not look at the environment settings.

D.L
  • 4,339
  • 5
  • 22
  • 45
  • Thank you for testing. I did some more testing and found out that i am getting the Error Code 0 (The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program.) when trying to start the process. I double checked my path (absolute path) but it still doesn't work. Any Idea what to do next? – Dost Apr 16 '22 at 13:48
  • which editor are you using ? how is it setup ? are you pointing to the correct version of python ? – D.L Apr 16 '22 at 19:07
  • i am using Pycharm – Dost Apr 17 '22 at 12:54
0

I solved the issue with the help of the qt-forum and @D.L's comment: https://forum.qt.io/topic/135863/qprocess-not-working-on-windows-works-fine-on-linux-and-osx/5

Additional to if __name__=='__main__': one has to change 2 things in order to run my code on Windows.

  1. Don't call python3 but give Qprocess the absolute path to the python.exe. Note that even though im running python3 it is called python.exe inside a Python3X folder, like: r'C:\Users\me\AppData\AppData\Local\Programs\Python\Python39\python'
  2. The same is true for the script you want run. Give the QProcess the whole absoltue path, like: r'C:\Users\Me\Desktop\dummyfolder\main_subprocess.py'.

For some reason QProcess::terminate(), which should be triggered once you press 'Stop', does not work now. The state of the Subprocess stays in 2 (The process is running and is ready for reading and writing.) but QProcess::kill() works fine for me.

`

Dost
  • 1
  • 2