在控制台界面中断滚动文本的一般方法

2024-06-02 05:13:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试在控制台中制作一个游戏,希望有滚动文本。我希望能够按一下键/键入enter键,跳过滚动并打印其余内容。 到目前为止,我尝试使用pygame(由于必须激活显示界面),asyncio和sys.stdin.read(1)(阻止在cmd上运行,并且没有在基于异步的ide中查询用户)

这是我最近的一次尝试

import asyncio,time,sys

global skip 
immutablesleep = 0.04
mutablesleep = [immutablesleep]

async def aprintl(string,sep="",end="\n",sleep=mutablesleep):
    global skip
    for letter in string+end:
        print(letter+sep,end="",flush=True)
        await asyncio.sleep(sleep[0])
    skip = True

async def break_print():
    global skip
    while not skip:
        ch = sys.stdin.read(1)
        if len(ch)>0:
            mutablesleep[0]=0
            skip = True
        await asyncio.sleep(0.1)    


def printl(*args):
    global skip
    skip = False
    mutablesleep[0] = immutablesleep
    asyncio.gather(aprintl(*args),break_print())

在建议模块时,请记住,我既想要操作系统独立代码,也想要在将模块冻结到exe时可以轻松连接到的模块

更新:

目前,该功能在中断慢速打印方面运行良好,但有两个问题仍然存在:
1: 按enter键的中断会切断打印线,使其无法读取
2: 即使在打印完成后,线程仍在等待enter

async def break_print():
    global skip, ch
    thread = Thread(target=t)
    thread.start()
    thread.join(timeout=0.1)
    while not skip:
        if len(ch) > 0:
            mutablesleep[0]=0
            skip = True
            ch = ''
        await asyncio.sleep(0.1)


def t():
    """Needed to read from stdin async"""
    global ch
    ch = sys.stdin.readline()

Tags: asynciotruereadasyncdefstdinsyssleep
1条回答
网友
1楼 · 发布于 2024-06-02 05:13:27

我相信你的问题与最后一行有关

asyncio.gather(aprintl(*args),break_print())

查看docs,函数签名如下:awaitable asyncio.gather(*aws, loop=None, return_exceptions=False).gather调用可能无法按预期工作,因为您没有传递可调用的列表,而是将aprintl(*args)传递给*aws,并且break_print()正在传递给loop参数

将该行更改为下面的行,然后查看它是否按预期工作。

asyncio.gather([aprintl(*args),break_print()])

更新

我让你的代码工作了,还有一些警告

import asyncio
import sys
from threading import Thread

global skip
ch = ''
immutablesleep = 0.04
mutablesleep = [immutablesleep]


async def aprintl(string,sep="",end="\n",sleep=mutablesleep):
    global skip
    for letter in string+[end]:
        if not skip:
            print(letter+sep,end="",flush=True)
            await asyncio.sleep(sleep[0])
    skip = True


async def break_print():
    global skip, ch

    while not skip:
        thread = Thread(target=t)
        thread.start()
        thread.join(timeout=.1)

        if len(ch) > 0:
            mutablesleep[0]=0
            skip = True
            ch = ''
        await asyncio.sleep(0.1)


def t():
    """Needed to read from stdin async"""
    global ch
    ch = sys.stdin.readline()


async def printl(*args):
    global skip
    skip = False
    mutablesleep[0] = immutablesleep
    await asyncio.gather(aprintl(*args), break_print())


if __name__ == '__main__':
    x = ['asdf ', 'asdf']*5000
    asyncio.run(printl(x))

发生了什么变化

  • 添加了t(),每次break_print在线程中运行.1秒,这是必需的,因为我相信初始代码没有运行的原因是因为它挂在sys.stdin.read(1)行上
  • 通过asyncio.run()运行printl()
  • 添加了一个if not skip:签入aprintl(),否则一旦跳过,它将打印整个输入

注意事项

  • 即使使用.read()也必须点击回车键才能停止打印输出。必须点击回车键。我使用readline(),因为它将返回在按下enter键之前输入的所有字符(这意味着,您可以检查以确保用户在按下enter键之前输入一些字符:len(ch.strip() > 0): do ...
  • 脚本即使在skip == True之后也不会退出。这可能是因为break_print()skip == True时不会退出,它将继续循环

我意识到这在您的用例中可能不起作用,但我希望它至少能给您一些想法

相关问题 更多 >