Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Python处理异步击键?_Python_Asynchronous_Keyboard Events_Interrupt Handling - Fatal编程技术网

如何使用Python处理异步击键?

如何使用Python处理异步击键?,python,asynchronous,keyboard-events,interrupt-handling,Python,Asynchronous,Keyboard Events,Interrupt Handling,我正在寻找向Python脚本发送击键的方法。在本例中,我试图让脚本检测是否按了任意键,而不仅仅是中断信号(ctrl+c,ctrl+d,…) 我已经检查了信号python模块。但它似乎只准备处理中断信号,而不是如果我按下“K”或“空格”的话。我在模块的官方文档中看到了这一点: import signal import os import time def receive_signal(signum, stack): print 'Received:', signum signal.si

我正在寻找向Python脚本发送击键的方法。在本例中,我试图让脚本检测是否按了任意键,而不仅仅是中断信号(ctrl+c,ctrl+d,…)

我已经检查了信号python模块。但它似乎只准备处理中断信号,而不是如果我按下“K”或“空格”的话。我在模块的官方文档中看到了这一点:

import signal
import os
import time

def receive_signal(signum, stack):
    print 'Received:', signum

signal.signal(signal.SIGUSR1, receive_signal)
signal.signal(signal.SIGUSR2, receive_signal)

print 'My PID is:', os.getpid()

while True:
    print 'Waiting...'
    time.sleep(3)
他们说:

为了向正在运行的程序发送信号,我使用命令行程序kill。为了产生下面的输出,我在一个窗口中运行signal_signal.py,然后在另一个窗口中运行kill-USR1$pid、kill-USR2$pid和kill-INT$pid

我很确定这个模块不是解决方案。您知道一些模块或东西可以帮助我异步发送击键到python脚本吗

非常感谢

我希望用户在任何时候都可以通过按键跳过一天、一个月或一台机器

啊。现在它有意义了

也不太确定这是否可能

一切皆有可能。对于一个真正的异步解决方案来说,这可能非常复杂

在避免轮询方法的同时,我能想到的唯一方法是
fork(2)
进程,让父进程监听按键,并向子进程发送信号,而子进程实际上完成了工作

像这样的

#!/usr/bin/env python

import sys, os, time, termios, tty, signal


# Define some custom exceptions we can raise in signal handlers
class SkipYear(Exception):
    pass

class SkipMonth(Exception):
    pass


# Process one month
def process_month(year, month):

    # Fake up whatever the processing actually is
    print 'Processing %04d-%02d' % (year, month)
    time.sleep(1)


# Process one year
def process_year(year):

    # Iterate months 1-12
    for month in range(1, 13):

        try:
            process_month(year, month)
        except SkipMonth:
            print 'Skipping month %d' % month


# Do all processing
def process_all(args):

    # Help
    print 'Started processing - args = %r' % args

    try:

        # Iterate years 2010-2015
        for year in range(2010, 2016):

            try:
                process_year(year)
            except SkipYear:
                print 'Skipping year %d' % year

    # Handle SIGINT from parent process
    except KeyboardInterrupt:
        print 'Child caught SIGINT'

    # Return success
    print 'Child terminated normally'
    return 0


# Main entry point
def main(args):

    # Help
    print 'Press Y to skip current year, M to skip current month, or CTRL-C to abort'

    # Get file descriptor for stdin. This is almost always zero.
    stdin_fd = sys.stdin.fileno()

    # Fork here
    pid = os.fork()

    # If we're the child
    if not pid:

        # Detach child from controlling TTY, so it can't be the foreground
        # process, and therefore can't get any signals from the TTY.
        os.setsid()

        # Define signal handler for SIGUSR1 and SIGUSR2
        def on_signal(signum, frame):
            if signum == signal.SIGUSR1:
                raise SkipYear
            elif signum == signal.SIGUSR2:
                raise SkipMonth

        # We want to catch SIGUSR1 and SIGUSR2
        signal.signal(signal.SIGUSR1, on_signal)
        signal.signal(signal.SIGUSR2, on_signal)

        # Now do the thing
        return process_all(args[1:])

    # If we get this far, we're the parent

    # Define a signal handler for when the child terminates
    def on_sigchld(signum, frame):
        assert signum == signal.SIGCHLD
        print 'Child terminated - terminating parent'
        sys.exit(0)

    # We want to catch SIGCHLD
    signal.signal(signal.SIGCHLD, on_sigchld)

    # Remember the original terminal attributes
    stdin_attrs = termios.tcgetattr(stdin_fd)

    # Change to cbreak mode, so we can detect single keypresses
    tty.setcbreak(stdin_fd)

    try:

        # Loop until we get a signal. Typically one of...
        #
        # a) SIGCHLD, when the child process terminates
        # b) SIGINT, when the user presses CTRL-C
        while 1:

            # Wait for a keypress
            char = os.read(stdin_fd, 1)

            # If it was 'Y', send SIGUSR1 to the child
            if char.lower() == 'y':
                os.kill(pid, signal.SIGUSR1)

            # If it was 'M', send SIGUSR2 to the child
            if char.lower() == 'm':
                os.kill(pid, signal.SIGUSR2)

    # Parent caught SIGINT - send SIGINT to child process
    except KeyboardInterrupt:
        print 'Forwarding SIGINT to child process'
        os.kill(pid, signal.SIGINT)

    # Catch system exit
    except SystemExit:
        print 'Caught SystemExit'

    # Ensure we reset terminal attributes to original settings
    finally:
        termios.tcsetattr(stdin_fd, termios.TCSADRAIN, stdin_attrs)

    # Return success
    print 'Parent terminated normally'
    return 0


# Stub
if __name__ == '__main__':
    sys.exit(main(sys.argv))

…应该可以做到这一点,尽管您会受到可以发送的不同信号数量的限制。

为了澄清这一点,您希望向类Unix操作系统上运行的Python脚本发送任意击键?没错!如果有不好的文字或语法错误,请编辑!嗯,你似乎经常使用“信号”这个词,信号和击键不是一回事。您想要接收击键的程序能否由您想要用来发送击键的脚本启动?您可以看一看:请自己澄清信号和键盘输入/击键之间的区别,因为信号是操作系统内部用来与进程对话的东西。是的。我在一年中的所有月份都有一个循环的
。对于每个月,脚本都会在该月的所有日子中循环。对于一个月中的每一天,脚本在一定数量的机器上循环,并开始对消耗量进行操作并打印结果。我希望用户在任何时候都可以通过按键跳过一天、一个月或一台机器。我不太确定这是否可能。太棒了!!非常感谢你的努力!!