0

I have an issue with Tkinter, I'm running this script "index.py" after clicking the button, the script starts running, but I do not get an output anywhere, any remarks?


from tkinter import *
import threading
import subprocess

root = Tk()

frame = Frame(root, width=300, height=300)
frame.pack()


def myClick():

    t = threading.Thread(target=run())
    t.start()


def run():
    arg = "python index.py"
    process = subprocess.check_output(arg)

    lab = Label(frame, text=process)
    lab.pack()


myButton = Button(root, text="run", padx=40, pady=10, command=myClick)
myButton.pack(pady=40)

root.mainloop()
Modestas
  • 55
  • 5
  • Cannot reproduce the issue in my Windows platform with Python 3.8.13. I can see the output of the script `index.py` (has only one line `print('hello')`) in the label. – acw1668 Aug 26 '22 at 08:14
  • Note that `arg` *should* be a list of strings. The way you use it results in different behavior on ms-windows and POSIX operating systems like macOS and Linux. See the `subprocess` documentation for details – Roland Smith Aug 26 '22 at 08:23
  • Maybe first use `print()` (and `print(type(...))`, `print(len(...))`, etc.) to see which part of code is executed and what you really have in variables. It is called `"print debuging"` and it helps to see what code is really doing. – furas Aug 26 '22 at 09:26
  • `target=` needs function's name without `()` - and it will later use `()` to start thread. At this moment you run code directly in current thread like this `result = run()` and `target=result`. But if you use thread correctly then you may have other problem - most GUIs don't like to use widgets in separated threads. It may need to use queue to send data to main thread and it may need to use root.after which periodically check queue and create widget with new text – furas Aug 26 '22 at 09:30
  • what index.py is doing? If it runs long time then subprocess waits for ends of thread and it will create Label after thread finish. And if index.py display in `stderr` (standard error) then it will not get it. It gets only `stdout` (standard output) – furas Aug 26 '22 at 09:32

3 Answers3

1

The way you are starting a subprocess does not work on all platforms.

As acw1668 commented, it works fine on ms-windows. But it does not work on POSIX platforms like macOS, Linux or *BSD:

> python
Python 3.9.13 (main, May 31 2022, 12:56:40) 
[Clang 13.0.0 (git@github.com:llvm/llvm-project.git llvmorg-13.0.0-0-gd7b669b3a on freebsd13
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> arg = "python index.py"
>>> process = subprocess.check_output(arg)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.9/subprocess.py", line 424, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/usr/local/lib/python3.9/subprocess.py", line 505, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/local/lib/python3.9/subprocess.py", line 951, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/local/lib/python3.9/subprocess.py", line 1821, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'python index.py'
>>> 

This is due to the different way that process creation works on different platforms.

Look closely at the last line of the error message. You have told subprocess to execute a file named python<space>index.py, which of course doesn't exist.

Convert arg into a list of strings, and it will work:

>>> arg = ["python", "index.py"]
>>> process = subprocess.check_output(arg)
>>> print(process)
b'Hello from index.py\n'

The following code should work everywhere:

def run():
    arg = ["python", "index.py"]
    process = subprocess.check_output(arg)

    lab = Label(frame, text=process)
    lab.pack()

EDIT1:

IDE's can do weird things with the standard output of your programs. And they might interact with scripts using subprocess, multiprocessing or threading in non-inuitive ways. When in doubt, first run your program from a command prompt. If it works there, it is an IDE problem.

In general, if you have any problem with a python script in an IDE or interactive environment, try saving it to a file and running it from a command prompt first.

Roland Smith
  • 42,427
  • 3
  • 64
  • 94
  • Thank you, your remark had fixed the bug, but the initial output problem is still present. None of the print() is displayed in GUI or IDE. Unfortunately I cannot post a picture here for you to see – Modestas Aug 26 '22 at 08:46
  • @Modestas It works in my RHEL 6.5 Linux with Python 3.9.7 and my Windows 7 with Python 3.8.13. – acw1668 Aug 26 '22 at 09:29
  • @Modestas if you using the standard IDE of python. There is a problem with printing in a different process. [See this thread](https://stackoverflow.com/a/35297841/13629335) – Thingamabobs Aug 26 '22 at 10:34
  • @Thingamabobs I'm using PyCharm on Win11 – Modestas Aug 26 '22 at 12:27
  • @RolandSmith tried that as well. At this point I think i'll take other routes to create an gui – Modestas Aug 26 '22 at 12:46
  • 1
    @Modestas you should include your system and environment information and state the full trace back if any. Also edit your question to contain a [mre]. I guess it's a lack of details to your question that it dosent work out for you – Thingamabobs Aug 26 '22 at 12:59
0

That's because at line 12, you use target=run() instead of target=run

John
  • 21
  • 3
0

I dont know what you are trying to achieve exactly, but the issue is with the process line.

So this correction works:

import threading
import subprocess

from tkinter import *

root = Tk()

frame = Frame(root, width=300, height=300)
frame.pack()


def myClick():

    t = threading.Thread(target=run())
    t.start()


def run():
    
    arg = "python index.py"
    # process = subprocess.check_output(arg)   # <--- error is here

    lab = Label(frame, text='hello')   # <---  this works
    lab.pack()




myButton = Button(root, text="run", padx=40, pady=10, command=myClick)
myButton.pack(pady=40)

root.mainloop()


So the result looks like this:

enter image description here

Every time you click it says "hello".

D.L
  • 4,339
  • 5
  • 22
  • 45
  • The script I'm calling prints a string after it's executed. I want that print to be displayed in my label – Modestas Aug 26 '22 at 07:53
  • for example I want these print to be displayed in my label ```if len(system_results) == len(expected_results) and len(system_results) == sum([1 for i, j in zip(system_results, expected_results) if i == j]): print("\nTest passed") else: print(f"\nTest failed\n expected results: {expected_results}\n got: {system_results}")``` – Modestas Aug 26 '22 at 07:55
  • well, it does that, but the way that you have it written, it looks like you are actually adding a new label each time, but that would be a different question. – D.L Aug 26 '22 at 07:55
  • btw: You don't need `subprocess` or `threading` to achieve this. Could have called the function to edit the label directly. – D.L Aug 26 '22 at 07:56
  • It's my first little project with Tkinter. That's why I'm asking help, I'm not sure what I need or don't need. – Modestas Aug 26 '22 at 07:58
  • it is a good first try. there are some helpful tutorials out there. Also, i always prefer an alias over a wildcard: so this is good `import tkinter as tk` and this is bad `from tkinter import *`.... reason is that with the alias, you know where the functions come from. – D.L Aug 26 '22 at 08:01
  • Thank you for that tip. Regarding my problem... I tried looking it up online but my research was not successful. May you please help me out with this output problem? – Modestas Aug 26 '22 at 08:03
  • You are welcome, please accept the answer if it was helpful. Also, use this guide for asking new questions: https://stackoverflow.com/help/minimal-reproducible-example – D.L Aug 26 '22 at 08:09
  • Your code is not working. we need this subprocess.check_output – toyota Supra Aug 26 '22 at 12:34
  • The call `subprocess.check_output` like this: https://stackoverflow.com/questions/14078117/how-do-you-use-subprocess-check-output-in-python – D.L Aug 26 '22 at 13:19