1

I am making a simple IDE with a text box and a run button. This asks the user to enter the filename, writes the code written to a file and runs that file. I want to show whatever is outputted from the console, such as a print, input, etc.. like IDE's do. Is this possible?

Here is my code:

from Tkinter import *
import tkFileDialog
import ScrolledText
import subprocess
filepath=""
def run():
    global filepath
    print "<<<<<<=====-------------Restart-------------=====>>>>>>"
    py=code.get(1.0,END)
    if filepath=="":
        filepath=tkFileDialog.asksaveasfilename()
        if ".py" not in filepath:
            filepath=filepath+".py"
    script=open(filepath, "w")
    script.write(py)
    script.close()
    p = subprocess.Popen(['python', filepath],
                         stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT,
                         )
    for line in iter(p.stdout.readline, ''):
        print line
    print "<<<<<<=====-------------EXECUTION FINISHED-------------=====>>>>>>"
root = Tk()
code=ScrolledText.ScrolledText(root)
code.pack()
run=Button(root,text="Run", command=run)
run.pack()
root.mainloop()
2
  • Of course it's possible. If it weren't possible, other IDEs couldn't do it, now could they? Try running the user's program as a subprocess and capturing its output. Commented Jul 5, 2014 at 18:23
  • Ha, good point, never realized how IDE's work until I tried making one! Commented Jul 6, 2014 at 10:24

1 Answer 1

2

Yes, just use the subprocess module.

Getting output in one go

import subprocess

output = subprocess.check_output(['python', filepath])

If you want to capture the standard error out of the called process as well as standard out use this instead:

output = subprocess.check_output(['python', filepath], stderr=subprocess.STDOUT)

Or if you want to capture them separately:

p = subprocess.Popen(['python', filepath],
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     )
out, err = p.communicate()

Getting the output as it's produced

This gives you the combined stdout and strerr output, line by line:

p = subprocess.Popen(['python', filepath],
                     stdout=subprocess.PIPE,
                     stderr=subprocess.STDOUT,
                     )

for line in iter(p.stdout.readline, ''):
    # process the line

Keeping the UI responsive

If you run the above code on the same thread as your GUI, you are essentially blocking the Tk's event loop from running while you are waiting for each line. This means that though you are getting each line in real-time, and writing it to your GUI, it won't update the display until the event loop gets to run again, and process all your calls to Tk.

You need to run the subprocess code on a new thread, and in your GUI thread, periodically check for new input.

I've done an example based on yours for you, you can find it here:

http://pastebin.com/FRFpaeJ2

Sign up to request clarification or add additional context in comments.

10 Comments

Printing err and out works, but how do I print it as it outputted in the same order? This runs the whole program and collect the errors and output and prints it after the main is terminated... I want it to print like a console I/O does.
See my edit for that. If you want stdout and stderr separately, then it's more complex, as you need to use threads. Lemme know if that's required.
So the edit will print all outputs and errors in the order they are sent out? What if I want it to print as it is sent out? In this case it outputs them in that order, but say I were to enter a code that prints "Hello World" and uses time.sleep(1) and prints it again. I want it to print and print the next statement after 1 second delay. This edit would merely print the two prints immediately after the program is finished running in the subprocess. Is there a way to do this?
Yes this version works, but I entered a code print "Hello" time.sleep(5) print "Hello", but when I hit run, it waits for 5 seconds for the program in the subprocess to finish and then prints the two hello worlds, I want it to print the first one as it is outputted and then the next one as it is outputted 5 seconds later.
I don't follow that last comment...?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.