18

在多线程跨平台 python3.3 应用程序上工作时,我遇到了一些我没有预料到的奇怪行为,也不确定是否会出现。问题在于 Windows 8input()在一个线程中调用该方法会阻塞其他线程,直到它完成。我已经在三台 Linux、两台 Windows 7 和一台 Windows 8 计算机上测试了以下示例脚本,并且这种行为仅在 Windows 8 计算机上观察到。这是 Windows 8 的预期行为吗?

测试.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')

复制.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)

更新:在尝试其中一个建议时,我意识到我匆忙得出结论,遗漏了一些明显的东西。我为一个错误的开始道歉。

正如 Schollii 建议的那样,只使用线程(没有子进程或 python 文件)会导致所有线程都向前推进,所以实际上input()在一个 python 进程中使用的问题会导致其他 python 进程阻塞/不运行(我不知道到底发生了什么)。此外,受影响的似乎只是 python 进程。如果我使用上面显示的相同代码(有一些修改)来执行带有 subprocess.Popen 的非 python 可执行文件,它们将按预期运行。

总结一下:

  • 使用 subprocess 执行非 python 可执行文件:无论是否调用input().
  • input()使用子进程执行 python 可执行文件:如果在原始进程中进行了调用,则创建的进程似乎不会运行。
  • 使用子进程通过调用input()新进程而不是原始进程来创建 python 进程:调用input()阻塞由“主”进程产生的所有 python 进程。

旁注:我没有 Windows 8 平台,因此调试/测试可能会有点慢。

4

2 回答 2

1

input因为在Python 3.0-3.2中存在几个问题,所以这个方法受到了一些影响。

我们可能又遇到了新的错误。

您可以尝试以下变体,即raw_input()“反向端口”(在Python 2.x中可用):

...
i = eval(input("-->"))
...
于 2013-10-22T08:13:51.007 回答
1

这是一个很好的问题,

因为您依赖于input()通常需要控制台输入的方法,

因为你有线程,所有线程都试图与控制台通信,

因此,我建议您使用任Producer-Consumer一概念或将所有输入定义到文本文件并将文本文件传递给程序。

于 2013-10-25T06:43:52.157 回答