如何强制 input() 停止并继续代码流

how to force input() to stop and continue the code flow

即使用户没有输入任何内容,我也需要退出包含输入语句的循环。它也从进程接收参数,并且必须立即评估内容。像这样:

import multiprocessing

def my_function (my_queue):
    var = ""
    #### some code which finally puts something in the queue ###
    my_queue.put(var)


def main():
    my_queue = multiprocessing.Queue()

    p1 = multiprocessing.Process (target=my_function, args =(my_queue,))
    p1.daemon = True
    p1.start()

    my_var = ""
    
    while (my_queue.empty() is True and my_var == ""):
        my_var = input ("enter a parameter for my_var: ")

    #### code that evaluates the queue and the input as appropiate

## I want to exit the loop if there's something in the queue even if the user hasn't written anything

这当然行不通。主循环堆叠在输入部分。有任何想法吗?我正在使用 Windows。提前谢谢大家!

试试这个:我们使用 os.kill 从子进程向父进程发送一个信号,这会引发一个我们捕获的异常以逃避 input 函数。

import multiprocessing
import signal
import time
import os


def my_function (my_queue, pid):
    var = ""
    #### some code which finally puts something in the queue ###
    time.sleep(3)
    my_queue.put(var)
    os.kill(pid, signal.SIGUSR1)


def interrupted(*args):
    print('Item added to queue before user input completed.')
    raise InterruptedError


def main():
    my_queue = multiprocessing.Queue()

    p1 = multiprocessing.Process (target=my_function, args =(my_queue,
                                                             os.getpid()))
#     p1.daemon = True
    p1.start()

    my_var = ""
    try:
        signal.signal(signal.SIGUSR1, interrupted)
        while (my_queue.empty() is True and my_var == ""):
            my_var = input ("enter a parameter for my_var: ")
    except InterruptedError:
        pass
    print('Processing results...')
    #### code that evaluates the queue and the input as appropiate

## I want to exit the loop if there's something in the queue even if the user hasn't written anything
if __name__ == '__main__':
    main()

以上代码仅适用于 Unix。我不知道以下代码是否有效 cross-platform,但它可能:

import multiprocessing
import signal
import time
import os


def my_function (my_queue, pid):
    var = ""
    #### some code which finally puts something in the queue ###
    time.sleep(3)
    my_queue.put(var)
    os.kill(pid, signal.SIGINT)

def interrupted(*args):
    raise InterruptedError


def main():
    print('I am %s!' % os.getpid())
    my_queue = multiprocessing.Queue()

    p1 = multiprocessing.Process (target=my_function, args =(my_queue,
                                                             os.getpid()))
    p1.daemon = True
    p1.start()

    my_var = ""
    try:
        signal.signal(signal.SIGINT, interrupted)
        while (my_queue.empty() is True and my_var == ""):
            my_var = input ("enter a parameter for my_var: ")
    except InterruptedError:
        time.sleep(0.1)
        if my_queue.empty():
            print('Exiting gracefully...')
            return
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    print('Processing results...')
    time.sleep(10)
    #### code that evaluates the queue and the input as appropiate

## I want to exit the loop if there's something in the queue even if the user hasn't written anything
if __name__ == '__main__':
    main()

一个大概是跨平台的答案,通过滥用 asyncio 模块。

我不完全明白我做了什么,我确信这是错误的形式,但我创建了两个并发任务,一个等待输入,一个检查队列中的值并引发中断错误。由于 return_when='FIRST_EXCEPTION' 设置,both 函数有必要引发异常。我通过异常返回了用户输入,因为该函数从不 returns.

import asyncio
import multiprocessing
import time
from aioconsole import ainput


def my_function(queue):
    time.sleep(3)
    queue.put(5)


async def my_loop(queue):
    while True:
        await asyncio.sleep(0.1)
        if not queue.empty():
            raise InterruptedError

async def my_exceptional_input():
    text = await ainput("Enter input:")
    raise InterruptedError(text)

async def main():
    queue = multiprocessing.Queue()
    p = multiprocessing.Process(target=my_function, args=(queue,))
    p.start()
    task1 = asyncio.create_task(my_exceptional_input())
    task2 = asyncio.create_task(my_loop(queue))
    result = await asyncio.wait([task1, task2], return_when='FIRST_EXCEPTION')
    try:
        task2.result()
    except asyncio.exceptions.InvalidStateError:
        text = str(task1.exception())
    except InterruptedError:
        text = ""
    print('Doing stuff with input %s...' % text)


if __name__ == '__main__':
    asyncio.run(main())

编辑:使用 'FIRST_EXCEPTION' 对我来说很愚蠢。我可以这样使用 'FIRST_COMPLETED':

import asyncio
import multiprocessing
import time
from aioconsole import ainput


def my_function(queue):
    time.sleep(3)
    queue.put(5)


async def my_loop(queue):
    while True:
        await asyncio.sleep(0.1)
        if not queue.empty():
            break


async def main():
    queue = multiprocessing.Queue()
    p = multiprocessing.Process(target=my_function, args=(queue,))
    p.start()
    task1 = asyncio.create_task(ainput("Enter text:"))
    task2 = asyncio.create_task(my_loop(queue))
    result = await asyncio.wait([task1, task2], return_when='FIRST_COMPLETED')
    try:
        text = task1.result()
        q = ""
    except asyncio.exceptions.InvalidStateError:
        text = ""
        q = queue.get()
    print('Doing stuff with input %s/%s...' % (text, q))


if __name__ == '__main__':
    asyncio.run(main())