Issues with the "subprocess" module in Python 3.9.1 (or 3.9.2) - "subprocess.Popen" doesn't work

Viewed 1548

When my script has the .pyw extension, the function subprocess.Popen doesn't work, but if I use the .py extension, it works. Actually the extension is not so important, the main point is if I use the terminal or not to run the script, if I don't use it I have the issue, otherwise no issues.

This wird behaviout happens only in my PC with Python 3.9.1 or 3.9.2 (the last version currently available). However I have another PC with Python 3.9.0, and there the issue doesn't exist.

I'll give you an example. here I have two scripts, below is the first one named main_script.pyw:

from tkinter import *
from tkinter import ttk
import sys, subprocess

def MyFunction():
    subprocess.Popen(["start", sys.executable, "script.py"], shell=True)

parent=Tk()
parent.geometry("300x250+370+100")
parent.title("Test")

TestButton=ttk.Button(parent, text="start", width=16, command=MyFunction)
TestButton.place(x=10, y=10)

parent.mainloop()

Here is the second one named script.py:

a=input("give me a number: ")

Both of them are placed in the same directory. The user can start the second script using the function subprocess.Popen only if the extension of the main script is .py, otherwise he can't. How can I solve the issue? Is it a BUG?

I attached a GIF too:

enter image description here

UPDATE! 1 I tried to install Python 3.9.0 in a virtual machine, and there I found the same issue described before! so, I can't understand why in my PC, with the same version, the script works. if I type python --version in my terminal the output is Python 3.9.0. Here is another GIF to show you that it works:

enter image description here

In the installation path (C:\Users\USER_NAME\AppData\Local\Programs\Python), I saw two folders, Python39 and Python38-32. Probably the second one is a refuse from an old installation, I don't know, but maybe it helps to make the script work. What do you think?

I just want to run CLI scripts via Tkinter as you saw in the last GIF (without using the terminal of course). How can I reach my goal?

UPDATE! 2 I'm not sure but, maybe it's a Windows issue. I tried to run Google Chrome using the subprocess.Popen(["start", sys.executable, "script.py"], shell=True) instruction (before you have to open the terminal in the Chrome installation folder C:\Program Files\Google\Chrome\Application) and it worked only in my PC where I never have issues, but with the other one Chrome didn't start, and in the terminal I got this output (I use ConEmu as terminal):

>>> subprocess.Popen(["start", sys.executable, "chrome.exe"], shell=True) 
<Popen: returncode: None args: ['start', 'C:\\Users\\aquer\\AppData\\Local\\...>

SyntaxError: Non-UTF-8 code starting with '\x83' in file C:\Program Files\Google\Chrome\Application\chrome.exe on line 2, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

Current directory:
C:\Program Files\Google\Chrome\Application

Command to be executed:
"C:\Users\USER_NAME\AppData\Local\Programs\Python\Python39\python.exe"   chrome.exe

ConEmuC: Root process was alive less than 10 sec, ExitCode=1.
Press Enter or Esc to close console...

I tried to open the terminal in Admin mode but, also in this case, Google Chrome didn't start. Where is the issue from your point of viewes?

2 Answers

I think that it is because for .py files Windows uses python.exe and for .pyw files Windows uses pythonw.exe. The problem is that sys.executable has the file location of the program used to start the main python file (python.exe when the extension is .py and pythonw.exe when the extension is .pyw). So the problem is that you are trying to start the .py program using the python executable that is for .pyw file extensions.

In cmd:

>>> import sys
>>> sys.executable
'C:\\Program Files\\Python37\\python.exe'

in IDLE (doesn't have the terminal window):

>>> import sys
>>> sys.executable
'C:\\Program Files\\Python37\\pythonw.exe'

Therefore, you have to decide which program (python.exe or pythonw.exe) you want to use. You can do it based on the file extension.

A simple solution would be to open a command prompt from your main_script.py manually, and execute script.py in there, if you really have to execute it as an extra process. If you do not have to, just add import script at the place you want the content of script.py to be executed, or, even better, wrap the code in script.py into a function, import script.py at the top of main_script.py and call the funcction at the approproate place. For the first solution, there is an example on DataToFish that has almost the same code as you (using tkinter GUI a.o., you have to scroll down a bit to find the example with a GUI). In short, you just have execute cmd /c {sys.executable} script.pyw from main_script.py.

Related