ModuleNotFoundError when running a python-script (python 3.11) with side-packages in PySide6.QProcess (Qt 6.6.0)

20 Views Asked by At

When running any Python script without side-packages using QProcess, the script is executed successfully. But when running the same script with dependencies (e.g.* import numpy*), it throws a ModuleNotFoundError.

script.py: import subprocess

v = subprocess.run(["pip", "-V"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
if v.stdout:
    print(v.stdout)
else:
    print("Error:", v.stderr)

try:
    f = subprocess.check_output(['pip', 'freeze'], stderr=subprocess.STDOUT)
    f_str = f.decode('utf-8')
    print(f_str) #**"numpy==1.26.4" was listed**

except subprocess.CalledProcessError as e:
    print("Error: ", e.output.decode('utf-8'))

import numpy as np **#Error occured here**

v = subprocess.run(["pip", "-V"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
if v.stdout:
    print(v.stdout)
else:
    print("Error:", v.stderr)

how the script was executed using QProcess:

import subprocess
from PySide6.QtCore import QProcess

class ProcessManager(QWidget):
#...
def start_process(self, abs_filepath, args):
        dir, fname = os.path.split(abs_filepath)
        deps_dir = os.path.join(os.path.dirname(__file__), "deps")
        self.check_requirements_installation(abs_filepath, deps_dir) #see below

        subprocess.run(["pip", "-V", "", "", ""], check=True)
        subprocess.check_output(['pip', 'freeze'], stderr=subprocess.STDOUT)

        self.process = QProcess()
        self.process.readyReadStandardOutput.connect(self.handle_output)
        self.process.readyReadStandardError.connect(self.handle_error)

        if self.process.state() == QProcess.NotRunning:
            self.process.start('python', [abs_filepath] + args) #args = [[sth, sth, sth], [..], ..]

        if not self.process.waitForFinished():
           self.print_to_console.emit('error', 'Error: Process finished prematurely' + self.process.errorString())
            return

        if self.process.exitStatus() != QProcess.NormalExit:
            self.print_to_console.emit('error', 'Error: Process exited abnormally' + self.process.errorString())
                return

As you can see in the code above, I tried to compare the python versions, as well as the found side-packages. all executions of pip commands (QProcess-script, Qt terminal, admin terminal) printed out the same content (pip 23.2.1 from C:\Program Files\Python311\Lib\site-packages\pip (python 3.11)). Since I installed numpy globally, it can also be found in the same path (C:\Program Files\Python311\Lib\site-packages\numpy).

#All Python paths are in PATH.

#Tried it by setting qt´s default python (Edit>Preferences>Python>Interpreters) as suggested here: Qt ImportError when running a python script with imports

#Furthermore, requirements.txt are checked and installed automatically, so they cannot be missing before executing the process: (check packages suggested here: Atom shows ModuleNotFoundError when running python script)

    def check_requirements_installation(self, main_dir, deps_dir):
        requirements_path = os.path.join(main_dir, 'requirements.txt')

        if os.path.exists(requirements_path):
            try:
                with open(requirements_path, 'rb') as file:
                    # Skip the BOM character if present
                    first_char = file.read(1)
                    if first_char != b'\xef\xbb\xbf':
                        file.seek(0)

                    requirements = file.read().decode('utf-16').splitlines()
                    installed_packages = subprocess.check_output(['pip', 'freeze'], text=True).splitlines()
                    missing_packages = [requirement for requirement in requirements if not any(requirement.split('==')[0] in package for package in installed_packages)]
                    for i in installed_packages:
                        print('installed', i)

                    if missing_packages:
                        self.print_to_console.emit('info', 'Some required packages are missing. Installing...')
                        for package in missing_packages:
                            print(package)
                            subprocess.run(["pip", "install", "-r", "requirements.txt", f"--target={deps_dir}"], check=True)

                        self.print_to_console.emit('info', 'All missing packages installed successfully.')
                    else:
                        self.print_to_console.emit('info', 'All required packages are already installed.')
            except Exception as e:
                self.print_to_console.emit('error', str(e))
        else:
            self.print_to_console.emit('warning', 'Please create a requirements.txt by opening your script in your ide, directing to its path inside the terminal and by executing "pip freeze requirements.txt" inside this terminal.')
            self.update_status_signal.emit('error', 'Error: The requirements.txt is missing next to your main script. Please add it to the same folder path.')
        return```


*# Additionally, I created a new venv for the script:
*```
    def get_venv(self, abs_filepath):
        venv_dir = os.path.join(os.path.dirname(__file__), "venv")
        if not os.path.exists(venv_dir):
            subprocess.run(["python", "-m", "venv", venv_dir], check=True)

        activate_script = os.path.join(venv_dir, "Scripts", "activate.bat")
        subprocess.run([activate_script], shell=True, check=True)

        deps_dir = os.path.join(os.path.dirname(__file__), "deps")
        self.check_requirements_installation(main_dir, deps_dir)

        env = QProcessEnvironment.systemEnvironment();
        env.insert("LD_LIBRARY_PATH", deps_dir)
        self.check_requirements_installation(main_dir, dir)

        return venv_dir

     def start_process(self, abs_filepath, args):

        #....
        venv = self.get_venv(abs_filepath)
        self.process = QProcess()
        self.process.setEnvironment(venv_dir)

Also, the process was executed using python3 and python (1) subprocess.run(["python", "-m", "venv", venv_dir], check=True) (2) subprocess.run(["python3", "-m", "venv", venv_dir], check=True)

But executing it with python3 lead to a "Python could not be found error" (also inside the terminal), altrough "where python3" prints out the correct file path to the user-specific python3 installation. The execution with the abs. path to python3 lead to a No access rights error.

Edit: Adding access rights to Qt for the whole PC did not make the issue go away. Does anyone have an idea what might cause the NoModuleFoundError when including side-packages in scripts which are run by QProcess?

0

There are 0 best solutions below