Python中实现输入超时及如何通过变量获取变量名
作者:佚之狗 发布时间:2021-02-17 03:17:48
背景介绍
开发中遇到了一个需求:程序运行到某处时需要用户确认, 但不能一直傻等, 后面的程序不能被一直阻塞, 需要有个超时限制, 也就是这个程序如果在一段时间后还没有得到用户输入就执行默认操作.
解决思路 – 多线程法
我就想到了用多线程的方式, 开启一个子线程用stdin(比如python的input函数)获取用户输入, 主线程里设置线程启动和超时.
创建线程
Python中使用多线程很方便, threading.Threaded(函数, 参数表)然后thread.start就好了. 只是有一点需要注意, 上面参数表必须是个元组, 也就是每个元素后面必须跟个逗号.
import threading
def anyFunction(aaa):
return str(aaa) #某种处理结果, 比如字符串
def manualInput(xxx):
data = input("请输入%s: " % xxx)
pass # 各种处理(比如数据转换什么的)
exampleThread = threading.Thread(target = manualInput, args = ( anyFunction("汪汪汪"), ), name = "喵喵喵")
exampleThread.start()
通过函数修改某个指定的(通过名字即字符串)变量的值
但这又出来一个问题, 如果不能使用全局变量, 该如何在另一个函数里修改其参数对应的内容呢? 这里的重点归结起来是"函数如何修改自身参数的内容".
于是我想到了一个骚透了的方法——改变量字典…… 因为python的变量是基于标签的. python中的变量大致可以理解成给内容贴上标签(每个标签对应一个变量名, 多个标签可能会引用同一个内容, 没被引用的内容就会被python释放), 每个标签都会有一个id(同时, 一个内存数据只要被引用那么自身也有个id). 示例:
print(id("喵喵喵"),"~~", id("喵喵喵"),"~~", id("喵喵喵"),"~~")
[Out]:
1392371317520 ~~ 1392371317520 ~~ 1392371317520 ~~
print(id("喵喵喵")); print(id("喵喵喵")); print(id("喵喵喵"))
[Out]:
1392371318576
1392371318000
1392371318288
python维护这些标签和内容的对应关系可以通过字典的方式来读取和修改, 改globals()[待改的变量的原名]的值就能通过指定变量名来修改变量了.
通过globals的字典修改变量
通过变量来获取变量的名字(字符串)
上面通过globals()[待改的变量的原名] = 新的内容的方式实现了修改变量的内容, 可是, 待改的变量的原名是个字符串, 怎么通过变量得到这个变量的名字呢?
一个思路是字典法.
把当前运行环境中的所有变量复制一份(浅拷贝和深拷贝效果都一样, 因为深浅拷贝前后都是相同的标签), 然后新建一个"标签id-变量名"的对照表字典, 利用字典赋值的特性, 遍历复制来的全局变量, 把id(变量值)作为key而变量名作为value, 即标签id-变量名字典[id(变量值)] = 变量名.
test = "some values"
变量A = "汪汪汪"
当前所有变量 = globals().copy()
print(当前所有变量)
[Out]:
{'__name__': '__main__',..., 'test': 'some values', '变量A': '汪汪汪'}
内容_变量名字符串对照表 = {}
for 变量名, 变量值 in 当前所有变量.items():
内容_变量名字符串对照表[id(变量值)] = 变量名
print(内容_变量名字符串对照表)
[Out]:
{2437914516272: '__name__',..., 2437948462576: 'test', 2437948432816:'变量A'}
这样一来就建立一个内容-变量名字符串的对照表, 又因为id(变量A) 和 id(变量A的值)是相等, 利用这个特性就能通过变量来取变量值了.
变量A的值 = 变量A
print(id(变量A的值)
[Out]:
2437948432816
内容_变量名字符串对照表[id(变量A的值)]
[Out]:
'变量A'
通过函数修改变量
上面这一堆头发就是为了动态、通用地修改变量, 封装成函数就能在任何地方调用和修改了.
def 一个实现变量修改函数(要改的变量, 提示语):
当前所有变量 = globals().copy()
变量id表 = {}
for 变量名, 变量值 in 当前所有变量.items():
变量id表[id(变量值)] = 变量名
待改的变量的原名 = 变量id表[id(要改的变量)]
新的内容 = str(input(提示语))
if len(新的内容) > 0 :
globals()[待改的变量的原名] = 新的内容
return 待改的变量的原名
tmp = "汪汪汪"
一个实现变量修改函数(tmp, "请输入新值: ")
[Out]:
请输入新值: 喵喵喵
'tmp'
print(tmp)
[Out]:
喵喵喵
总结(demo)[不想看中间过程的话可以直接看这]
import time, threading
# 这里的demo是为了通用化. 因为在一个线程中再嵌套另个线程的话, 嵌套的线程获取不到所有变量
class ThreadWithReturn(threading.Thread):
def __init__( self, target = None, args = () ):
super(ThreadWithReturn,self).__init__()
self.func = target
self.args = args
def run(self):
self.result = self.func(*self.args)
def getResult(self):
try:
return self.result
except Exception as errInfo:
print("遇到错误: ", errInfo)
return None
def 一个实现变量修改函数(要改的变量, 提示语):
当前所有变量 = globals().copy()
变量id表 = {}
for 变量名, 变量值 in 当前所有变量.items():
变量id表[id(变量值)] = 变量名
try:
待改的变量的原名 = 变量id表[id(要改的变量)]
except KeyError:
print("***debug: 在不同的线程中运行, 获取不到出入变量的名字")
待改的变量的原名 = None
新的内容 = str(input(提示语))
if len(新的内容) > 0 :
if 待改的变量的原名 != None:
globals()[待改的变量的原名] = 新的内容
else:
新的内容 = None
return [待改的变量的原名, 新的内容]
def Gexit():
exitConfirm = "u"
waitForConirm = ThreadWithReturn( target = 一个实现变量修改函数, args = (exitConfirm, "收到了退出信号, 默认30秒后退出, 是否现在退出呢? (Y/n) 请输入: ",) )
waitForConirm.start()
waitForConirm.join(30)
try:
exitConfirm = waitForConirm.getResult()[1]
print("***debug, got:", exitConfirm)
except Exception as errInfo:
print("***debug:", errInfo)
exitConfirm = "u"
if exitConfirm == "u":
print("等待超时, 开始退出流程...")
exitConfirm = "Ytt"
if exitConfirm == "Ytt" or exitConfirm == "Y":
if exitConfirm == "Y":
print("确认退出, 开始退出流程...")
pass # 这里放程序退出逻辑
if exitConfirm == "n":
print("取消退出, 继续运行...")
pass # 这里放继续运行的逻辑
return 0
Thread_waitForExit = threading.Thread(target = Gexit, args = ())
Thread_waitForExit.start()
Thread_waitForExit.join(45)
总结
以上所述是小编给大家介绍的Python中实现输入超时及如何通过变量获取变量的名字网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
来源:https://blog.csdn.net/qq_39707057/article/details/104002512
猜你喜欢
- 无法导入本地安装好的第三方库一、安装第三方库1、 Anaconda安装(1)、打开“cmd”窗口(快
- 本文实例讲述了JS实现简易图片轮播效果的方法。分享给大家供大家参考。具体如下:这里使用JS制作简易图片轮播效果:制作比较粗糙,使用的图片是w
- 原文:http://www.smashingmagazine.com/ ... emarkable-favicons/翻译:Blank(怿飞
- 背景之前是用的是typora来写的文章,最近typora最近开始收费了,所以就不想用了,于是找到了一个替代品MarkText,感觉跟typo
- 我们在使用Django过程中,数据库往往是离不开的,比较长常用的是MySQL数据库,但在使用过程中,对Python不同的版本对用的库也不一样
- python中eval和int的区别是什么?下面给大家介绍一下:1.eval()函数eval(<字符串>)能够以Python表达
- 一、前言Python logging 模块定义了为应用程序和库实现灵活的事件日志记录的函数和类。程序开发过程中,很多程序都有记录日志的需求,
- 简介TensorFlow 是一个端到端开源机器学习平台。它拥有一个全面而灵活的生态系统,其中包含各种工具、库和社区资源,可助力研究人员推动先
- 用户登录验证脚本,Chkpwd.asp<% '=======用户登录验证脚本======= '
- 目录 一,抓取情况描述二,网页分析三,程序编写 一,抓取情况描述1.抓取的页面需要登陆,以公司网页为例,登陆网址http
- 需求需要生成一个宣传的图片分享到朋友圈,这个宣传图片包含二维码,包含不同的背景图片和不同的文字。对于这种图片生成,我们考虑过使用服务端生成,
- 高级语言不能直接被机器所理解执行,所以都需要一个翻译的阶段,解释型语言用到的是解释器,编译型语言用到的是编译器。编译型语言通常的执行过程是:
- 如下所示:ffmpeg中文文档:http://linux.51yip.com/search/ffmpegffmpeg -i test_bao
- 简单的显示记录已经掌握,现在需要的就是通过ASP将信息内容插入到数据库中。一、拥有数据库cnbruce.mdb本数据库的作用就是用来 * 入数
- 今天在数据分析时遇到了一个小问题,这时才发现自己的基础知识真的不牢固,所以这里记录一下解决方法问题:我在处理完数据后得到的是一个列表,其中放
- virtualenv介绍virtualenv为应用提供了隔离的Python运行环境,解决了不同应用间多版本的冲突问题。virtualenv把
- 使用Python+OpenCV实现鼠标画框的代码,供大家参考,具体内容如下# -*-coding: utf-8 -*-""
- 分享一下 在3est活动中学习的godlong的 代码如下:<% Set xPost = createObject("Mi
- 看到论坛上有人模仿alert,自己也写了一个。本来想模仿winapi里的MessageBox ;但可惜js 不支持,阻塞模式。返回值只能用异
- 一个改进的仿google页面拖拽效果,移植方便。web2.0网站经常会用有这个拖拽页面布局的功能,如果你也想给你的网站加上这个有趣的功能,不