python获取控制台输出内容_【编程自学笔记】有关Python控制台“同时”输入与输出,curses库相关...

写在前面,我是个文科生,非相关专业人士,从未接受过任何编程类的系统教育或者培训(哦,大学考计算机找培训班学过一个多月c语言)。所有这方面的知识或者说认识及经验都是自己查阅相关资料得来。有不周全的地方希望指正,大佬勿喷。写这方面的东西主要是给自己留个笔记(如果以后有心情还会写点别的),也斗胆抛砖引转一下。4adb9255ada5b97061e610b682b8636764fe50ed.png

相关场景:

在进行这类基于控制台输入输出的编程测试中,往往会遇到一种情况,就是当一个线程a向控制台显示文字时,如果另一个线程b使用input,等待用户输入时。输出信息就会扰乱输入信息。这个扰乱指的是人类的操作方面,打字打一半,突然刷出来一条信息,打字的前一半就被带走了,后一半可能会在奇怪的地方尬住。。。

所以说这类情况不仅仅是python,其实只要是基于控制台交互的程序可能都有这方面的问题。除非在程序设计上尽力避免这种情况发生,但就很别扭。

后来我无聊在搞mc服务器的时候,发现那个服务端的交互是java基于控制台的,而且人家可以输入输出两不耽误,管理员可以随时在控制台使用相关命令。如图1edc2998baef04e7f2317e1be8bd4bb70a8d13d7.png请无视无脑插件刷屏

所以,这个事是有解决方案的!但是遗憾的是在百度上翻了很久,我并没找到相关文章。也许是我输入的关键字姿势不对吧╮(╯▽╰)╭

再后来,我在做一个试图在终端划分区域的程序时翻找到了一个叫做curses的神奇(又智障)的库。我也不知道python里对这些东西叫库对不对,非专业人员请见谅。所以我打开了新世界的大门。4adb9255ada5b97061e610b682b8636764fe50ed.png

关于curses库:

下面引用A.M. Kuchling, Eric S. Raymond发表的相关介绍,(相关链接见文章末尾参考资料curses 是什么?

curses 库为基于文本的终端提供了独立于终端的屏幕绘制和键盘处理功能;这些终端包括 VT100,Linux 控制台以及各种程序提供的模拟终端。显示终端支持各种控制代码以执行常见的操作,例如移动光标,滚动屏幕和擦除区域。不同的终端使用相差很大的代码,并且往往有自己的小怪癖。

上面那段话用人话讲哈,就是它可以实现对终端(屏幕或者窗口)进行分区域控制,你甚至可以控制每一个字符出现的位置,甚至颜色等样式。而且它还支持一个用户输入模块Textbox,wow是不是一种熟悉的感觉出来了(gui开发狂喜)。不过,此Textbox非彼Textbox,它要原始的多,后面会提到。

于是“多年”的vs studio使用者突然就顿悟,控制台输入输出这个事,只要用不同的线程分别控制终端不同的区域,就可以实现“同时”的输入输出啦。。。啊,其实做过gui编程开发就会知道,很多时候gui的输入输出也会使用多线程去优化,比如java的jprogressbar的进度刷新,还有微软系的窗口内容刷新等等。。。所以我就开始了对curses的学习,狂啃各种教程。然而事实上就会发现百度到90%的所谓教程都是复制粘贴上面那个官方的指引。啧

下面就归纳一些我遇到的curses坑和吐槽。

curses在import之前需要用pip install一下,安装方式见文章末尾参考资料。对中文(非英文)字符支持十分不友好

在显示方面,我在微软visual studio code的调试终端上还算可以,但是一旦py脚本运行在cmd的窗口下,汉字会诡异的叠加在一起。。。如图:533bd7bec86f14b400bb4837cf037ba97133ec16.png这是vs code的调试终端

58962ed96f5f52267b92438354c4b3a2a5ffde0f.png这是cmd窗口,我哭了你呢

也许你会好奇可不可以在汉字中间插空格,事实是可以的,但是那些显示正常的终端咋办,,,所以对中文显示不友好。

然后,上面说的那个textbox是完全不支持中文输入的,对没错,它不接收win10输入法输入的中文字符。。。行吧。别的输入法我懒得测试,复制粘贴懒得测了,这方面没有图。计量单位

不像一般的gui开发,都使用像素,或者一些相对的单位。curses的长宽及位置定位的单位均是单个英文字符,对没错,就是字符。。。宽就是你终端能显示的单行字符数,高就是你终端能显示的最大行数。如果你向终端添加的字符定位超过这个长宽上限,程序就报错崩了,崩了!!!

还有一点,在curses启动的时候,它就会获得你终端的最大长宽数据,如果你后面手欠调整了终端窗口(如果有的话)的大小,那么会引发未知的奇怪的bug。所以脚本启动后就不要去拉终端的窗口大小了。会变得奇怪起来。像一些窗口尺寸改变的事件监听是不存在的。

奇怪的位置参数定义

如果你去看了那篇介绍文章,你会发现,curses对位置(x,y)坐标的定义顺序是反过来的,就是说类似这样win = curses.newwin(height, width, begin_y, begin_x),对的,就是变成了(y,x)

已经显示的内容不能更改,除非全删

curses对于已经显示在屏幕上的字符,是无法通过相关“样式设置”改变它的位置或者内容,只能用clear()和refresh()去清空或者刷新相关区域。

curses就像那种老式的需要放置实体幻灯片的幻灯机,每一个画面(帧)一旦显示就是死的了,你只能增加,不能减少也不能改变已经显示的。只能完全清空,再去修改你的幻灯片,然后显示下一个画面(帧)。

像html通过js改变css实现画面内容变化,这样高级的功能是不存在的。

显示区域划分

这也是curses最大的用处和特点了,有pad和win两种,比较简单的就是win,它是借用了window这个词,但它跟我们常规认知的窗口并不相同。它就是简单的在终端屏幕上划分一个矩形区域。。。然后根据我上面的思路分别用线程去控制这些区域,就可以达到交互目的。365e9419fd500658bec597e7c92e770589ad3acb.png简单的划分没有两行字符输入进同一个Textbox……

Textbox模块虽然有的确有接收输入的能力,也能响应回车enter作为输入结束。但是它并不会清空自己,除非你自己用←删除。

所以为了实现输入一行回车后清空的效果,就要clear()textbox所在区域,textbox本身是没有清空的。就很神奇,然后当你clear()了textbox所在区域那么textbox本身也会被clear。。。所以除非你只需要输入一行就再也不输入别的东西了,那么你就要在一个循环里,在区域添加textbox,等待输入,得到回车后的信息,清空区域,然后添加textbox循环等待下一次输入。

另外使用textbox的gather()函数获得用户输入字符串时,得到的字符串长度比实际内容大1,我估计那个1也许是什么结尾标识符一类的东西,所以在进行比对时要对gather()返回的结果进行截取。

下面我给出我自己写的一个测试demo,在这段脚本里,我实现了显示区域字符达到区域行数上限后,向上滚动(但是不支持翻页或者滚轮),然后一个后台进程不断循环每一秒向显示区域添加文本。用户可以通过输入来交互,或者退出整个程序。b22179fce32a1b5b86b34b0351b11fa90d35e73f.png可以向上滚动

317c1193b9ecbaf42c495fae1721bee2d0f0e48b.png响应终端输入

c8b286cbc01585f2ab6c45c745ebedf3435bd1f7.png可以通过预设字符串(命令)实现整体退出

测试脚本网盘链接: https://pan.baidu.com/s/18PcyqbOaosl0XLt1A5maRA 提取码: 2d9e

说明一下,这个demo写的有点别扭,甚至用了两种线程的启动方式,因为这个东西我后面有别的用,这里就是展示下效果,思路和效果都是可以的。

脚本运行环境,win10 64位,python3.7

参考资料:

关于curses

https://docs.python.org/zh-cn/3/howto/curses.html

curses的安装

https://www.cnblogs.com/klb561/p/9271322.html

关于多线程的启动与终止

https://blog.csdn.net/ejennahuang/article/details/85060882

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值