Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

input() blocks other python processes in Windows 8 (python 3.3)

Working on a multi-threaded cross-platform python3.3 application I came across some weird behavior I was not expecting and am not sure is expected. The issue is on Windows 8 calling the input() method in one thread blocks other threads until it completes. I have tested the below example script on three Linux, two Windows 7 and one Windows 8 computers and this behavior is only observed on the Windows 8 computer. Is this expected behavior for Windows 8?

test.py:

import subprocess, threading, time

def ui():
    i = input("-->")
    print(i)

def loop():
    i = 0
    f = 'sky.{}'.format(i)
    p = subprocess.Popen(['python', 'copy.py', 'sky1', f])
    t = time.time()
    while time.time() < t+15:
        if p.poll() != None:
            print(i)
            time.sleep(3)
            i+=1
            f = 'sky.{}'.format(i)
            p = subprocess.Popen(['python', 'copy.py', 'sky1', f])
    p.terminate()
    p.wait()

def start():
    t1 = threading.Thread(target=ui)
    t2 = threading.Thread(target=loop)
    t1.start()
    t2.start()
    return t2

t2 = start()
t2.join()
print('done')

copy.py:

import shutil
import sys

src = sys.argv[1]
dst = sys.argv[2]

print('Copying \'{0}\' to \'{1}\''.format(src, dst))
shutil.copy(src, dst)

Update: While trying out one of the suggestions I realized that I rushed to a conclusion missing something obvious. I apologize for getting off to a false start.

As Schollii suggested just using threads (no subprocess or python files) results in all threads making forward progress so the problem actually is using input() in one python process will cause other python processes to block/not run (I do not know exactly what is going on). Furthermore, it appears to be just python processes that are affected. If I use the same code shown above (with some modifications) to execute non-python executables with subprocess.Popen they will run as expected.

To summarize:

  • Using subprocess to execute non-python executable: works as expected with and without any calls to input().
  • Using subprocess to execute python executable: created processes appear to not run if a a call to input() is made in the original process.
  • Use subprocess to create python processes with a call to input() in a new process and not the original process: A call to input() blocks all python processes spawned by the 'main' process.

Side Note: I do not have Windows 8 platform so debugging/tests can be a little slow.

like image 640
redmaw Avatar asked Oct 17 '13 01:10

redmaw


2 Answers

Because there are several problems with input in Python 3.0-3.2 this method has been impacted with few changes.

It's possible that we have a new bug again.

Can you try the following variant, which is raw_input() "back port" (which was avaiable in Python 2.x):

...
i = eval(input("-->"))
...
like image 120
Colin O'Coal Avatar answered Oct 07 '22 00:10

Colin O'Coal


It's a very good problem to work with,

since you are dependent with input() method, which, usually needs the console input,

since you have threads, all the threads are trying to communicate with the console,

So, I advice you to use either Producer-Consumer concept or define all your inputs to a text file and pass the text file to the program.

like image 36
Siva Cn Avatar answered Oct 07 '22 00:10

Siva Cn