在用户输入时终止包含while循环的多个进程

时间:2014-03-13 22:14:59

标签: python loops input multiprocessing terminate

这是通过以下组合创建的:

代码的想法是,while循环执行某些操作的两个函数同时运行,并且可以在用户按Enter键时停止。

import sys, select, os, datetime
from multiprocessing import Process
from time import time

def func_control():
    global switch
    switch = 1
    while True:
        #os.system('cls' if os.name == 'nt' else 'clear')
        print "I'm doing stuff. Press Enter to stop me!"
        if sys.stdin in select.select([sys.stdin], [], [], 0)[0]:
            line = raw_input()
            switch = 0
            break

def func_1():
    global i1
    i1 = 0
    while switch != 0:
        i1 = i1+1
    return 0

def func_2():
    global i2
    i2 = 0
    while switch != 0:
        i2 = i2+1
    return 0

def start_fcontrol():
    while time() < start_time: pass
    func_control()

def start_f1():
    while time() < start_time: pass
    func_1()

def start_f2():
    while time() < start_time: pass
    func_2()        

switch = 1
i1 = 0
i2 = 0
procs = []
procs.append(Process(target=start_fcontrol))
procs.append(Process(target=start_f1))
procs.append(Process(target=start_f2))
start_time = time() + 1
map(lambda x: x.start(), procs)
map(lambda x: x.join(), procs)
print "i1 = ", i1
print "i2 = ", i2

代码抛出以下错误,当使用第一个链接中提供的代码时,该错误不会发生:

I'm doing stuff. Press Enter to stop me!
Process Process-1:
Traceback (most recent call last):
  File "/usr/lib/python2.6/multiprocessing/process.py", line 232, in _bootstrap
    self.run()
  File "/usr/lib/python2.6/multiprocessing/process.py", line 88, in run
    self._target(*self._args, **self._kwargs)
  File "atest.py", line 31, in start_fcontrol
    func_control()
  File "atest.py", line 12, in func_control
    line = raw_input()
EOFError: EOF when reading a line

我试图尽可能保持代码干净。

2 个答案:

答案 0 :(得分:2)

丑陋,但它确实有效。通过共享内存完成同步。并且您需要将stdin文件描述符传递给子进程并在那里打开它。

import sys, select, os, datetime
from multiprocessing import Process, Value
from time import time

def func_control(fileno, switch):
    sys.stdin = os.fdopen(fileno)  #open stdin in this process

    print "I'm doing stuff. Press Enter to stop me!"
    some_str = raw_input("> ")
    switch.value = 0
    return

def func_1(i1, switch):
    i1.value = 0
    while switch.value != 0:
        i1.value = i1.value+1
    return 0

def func_2(i2, switch):
    i2.value = 0
    while switch.value != 0:
        i2.value = i2.value+1
    return 0

def start_fcontrol(start_time, fn, switch):
    while time() < start_time.value: pass
    func_control(fn, switch)

def start_f1(i1, start_time, switch):
    while time() < start_time.value: pass
    func_1(i1, switch)

def start_f2(i2, start_time, switch):
    while time() < start_time.value: pass
    func_2(i2, switch)        

switch = Value('i', 1)
i1 = Value('i', 0)
i2 = Value('i', 0)
start_time = Value('d', time() + 1)

fn = sys.stdin.fileno() #get original file descriptor

procs = []
procs.append(Process(target=start_fcontrol, args=(start_time, fn, switch)))
procs.append(Process(target=start_f1, args=(i1, start_time, switch)))
procs.append(Process(target=start_f2, args=(i2, start_time, switch)))
map(lambda x: x.start(), procs)
map(lambda x: x.join(), procs)
print "i1 = ", i1.value
print "i2 = ", i2.value

答案 1 :(得分:1)

正如@Silas Ray所说,当你有不同的进程时,你不能指望这些全局变量。也许你应该使用Threads。它就像你所做的一样简单,但对你有更多的好处。查看示例。 我已经过测试,似乎有效

非常重要的是你将线程标记为守护程序,这意味着它们将在主进程停止时死亡! : - )

from threading import Thread

def func_control():
    global switch
    switch = 1
    while True:
        #os.system('cls' if os.name == 'nt' else 'clear')
        print "I'm doing stuff. Press Enter to stop me!"
        if sys.stdin in select.select([sys.stdin], [], [], 0)[0]:
            line = raw_input()
            switch = 0
            break

def func_1():
    global i1
    i1 = 0
    while switch != 0:
        i1 = i1+1
    return 0

def func_2():
    global i2
    i2 = 0
    while switch != 0:
        i2 = i2+1
    return 0

switch = 1
i1 = 0
i2 = 0

myThread1 = Thread(target=func_1)
myThread1.daemon = True

myThread2 = Thread(target=func_2)
myThread2.daemon = True

myThread1.start()
myThread2.start()

func_control()