2013-10-17 7 views
18

マルチスレッドクロスプラットフォームpython3.3アプリケーションで作業しています。私は予想外の動きを見ました。この問題はWindows 8で、あるスレッドのinput()メソッドを呼び出すと、完了するまで他のスレッドをブロックします。私は3つのLinux、2つのWindows 7と1つのWindows 8コンピュータで以下のサンプルスクリプトをテストしましたが、この動作はWindows 8コンピュータでのみ確認されています。これはWindows 8の動作ですか?input()はWindows 8(python 3.3)の他のpythonプロセスをブロックします。

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) 

アップデート: 私は何かを明らかに不足しているという結論に駆けつけことに気づい候補の1つを試しながら。私は間違ったスタートに降りることをお詫びします。

Scholliiさんは、スレッド(サブプロセスやPythonファイルなし)を使用すると、すべてのスレッドが進行して問題が実際には1つのpythonプロセスでinput()を使用していることが示唆されています。正確に何が起こっているか)。さらに、影響を受けるのはちょうどPythonプロセスであるようです。上記の同じコードを(いくつかの変更を加えて)使用して、非python実行可能ファイルをsubprocess.Popenで実行すると、期待どおりに実行されます。

要約すると:

  • を非pythonの実行可能ファイルを実行するためのサブプロセスを使用した:とし、input()への呼び出しなしで期待通りに動作します。
  • サブプロセスを使用してpython実行可能ファイルを実行する:元のプロセスでinput()を呼び出した場合、作成されたプロセスは実行されないように見えます。
  • input()を呼び出すと、元のプロセスではなく、input()を呼び出すと、 'main'プロセスによって生成されたすべてのpythonプロセスがブロックされます。

サイドノート:Windows 8プラットフォームを使用していないため、デバッグ/テストが少し遅くなる可能性があります。

+2

あなたの 'copy.py'スクリプトの名前を変更すると助けになりますか? Pythonインタプリタを起動し、 'import shutil'と入力すると、Pythonはローカルフォルダの' copy.py'ファイルを移動するので、私はエラーになります。 –

+0

@ LukeWoodward:私はそれが 'copy_loop.py'であるべきだと思う。 –

+1

Win 8でソースからPythonをビルドし、デバッガからpython test.pyを実行し、デバッガを介して実行を一時停止することができます。ブロックされている呼び出しが8でブロックされているが7ではブロックされている理由を調べることができます。 – Schollii

答えて

1

にいくつかの問題があるため、Python 3.0-3.2にこのメソッドはほとんど影響を与えませんでした。

新しいバグが再び発生する可能性があります。

raw_input() "バックポート"(これはのPython 2で利用可能でした)を試すことができますか?X):あなたがスレッドを持っているので、通常はすべて、

をコンソール入力を必要とし、input()方法、と依存しているため、

... 
i = eval(input("-->")) 
... 
+4

これは質問に関係するとは思わない。まず、 'raw_input()'バックポートではなく、Python 3.xで使われるPython 2.xの 'input()'と同等のものを表示しています。 Python 3の 'input()' *はPython 2の 'raw_input()'です(多かれ少なかれ)。第2に、別の呼び出しでブロック関数をラップすると、ブロックされなくなります。 –

1

それは、

で動作するように非常に良い問題ですスレッドはコンソールと通信しようとしています

したがって、Producer-Consumerのいずれかの概念を使用するか、すべての入力をテキストファイルに定義してテキストファイルをプログラムに渡すようにアドバイスします。

+0

少し詳しく説明できますか?私のプログラムでは、(メインプロセスのスレッド内の)input()への呼び出しは、すべてのpythonプロセスとスレッドによって行われます。ノンブロッキングインプットメソッドはおそらく問題を解決するでしょうが、それは単に問題を回避するだけです。 – redmaw

関連する問題