Python IDLE running code differently than other IDEs

Question:

I’m trying to get threading to work with a Socket network to accept clients. I had that working fine, but now I have discovered an issue.

Here is the code:

clients = []

def myFunction():    #Not too relevant I think
    server.listen(0)
    conn, addr = server.accept()
    print(conn)
    clients.append(conn, addr)
    threading.Thread(myFunction)

threading.Thread(myFunction)
input("Hit enter to finish...")
print(clients)

Now this should return something like this, which it does on all the IDEs I have tried (PyCharm, Sublime text editor, etc.):

Hit enter to finish...
*2 users connect*
192.168.0.5 # this is the contents of conn
192.168.0.12
*hit enter*
192.168.0.5, 192.168.0.12

However, in Python’s own IDLE, the threading seems unable to print anything until I press Enter, with the exact same code, like so:

Hit enter to finish...
*2 users connect*
*hit enter*
192.168.0.5
192.168.0.12
192.168.0.5, 192.168.0.12

This isn’t what I want because my code will run in Python IDLE once its finished, so it needs to work here because of this.

Asked By: Dan P

||

Answers:

As IDLE’s name implies, it is primarily a development (and learning) environment. It is aimed especially at beginners. Use for running finished code is at best secondary, and is usually not an advantage.

The IDLE Doc chapter, which can be viewed in IDLE itself with Help => IDLE Help, has a subsection (3.3) IDLE-console differences. It begins

With rare exceptions, the result of executing Python code with IDLE is intended to be the same as executing the same code in a console window. However, the different interface and operation occasionally affect visible results.

The big difference in operation is that your code is executed in a separate Python process, with standard input and output going through a socket connection. This means that all stdout output from your program goes through IDLE code, which inserts it in a tk Text widget, rather than being sent directly to the OS screen manager.

In the case of input(), IDLE stops displaying output until after the the user hits return. (This is true even with an empty prompt.) I consider this an improvement over having output splattered in the middle of user input. Your code cannot run as is, but the following does.

import threading, time

def myFunction():
    time.sleep(1)
    print('Interruption from thread')

thread = threading.Thread(target=myFunction)
thread.start()
s =input("Hit enter to finish...")
print(s)

In IDLE 3.7.0b3 on Win10, I see something like

Hit enter to finish...skjfsjflsjfljsflsfjls
Interruption from threadskjfsjflsjfljsflsfjls

(I don’t know why the ‘n’ after ‘thread’ is suppressed.)
In Command Prompt I see

Hit enter to finish...ksjfkjsInterruption from thread
fjsfjsfkjsfljksfjkfs
ksjfkjsfjsfjsfkjsfljksfjkfs

The same issue occurs when inputting code after >>>:. Change my code to

import threading, time

def myFunction():
    time.sleep(2)
    print('Interruption from thread')

thread = threading.Thread(target=myFunction)
thread.start()

With IDLE:

>>> Interruption from thread
if a = 3:

In Command Prompt entering the same header with the same timing:

C:UsersTerry>python -i -m a.tem
>>> if aInterruption from thread
 = 3

If I better understood the relevant IDLE code, I would have the interrupt line inserted on a line before the prompt. I might also do the same during input(). Fortunately, output from threads or async tasks is not common, especially for beginners.

ADDENDUM: If one runs IDLE from a command line with python -m idlelib -n it runs in one process and thread output is not blocked. I don’t know if other issues will arise in this mode (which is not currently tested).

We (IDLE maintainers) have agreed that the blocking should be stopped in normal, two process mode and have a idea of why it happens.

Answered By: Terry Jan Reedy

A solution has been discussed, but not yet implemented. IDLE Shell – input() blocks output from another thread #83905. It seems the only way to work around it using IDLE is to launch IDLE with a ‘-n’ command line option to stop IDLE from launching its subprocess.

Answered By: Paul Gardner
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.