Python中实现输入超时及如何通过变量获取变量名


Posted in Python onJanuary 18, 2020

背景介绍

开发中遇到了一个需求:程序运行到某处时需要用户确认, 但不能一直傻等, 后面的程序不能被一直阻塞, 需要有个超时限制, 也就是这个程序如果在一段时间后还没有得到用户输入就执行默认操作.

解决思路 ? 多线程法

我就想到了用多线程的方式, 开启一个子线程用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()[待改的变量的原名]的值就能通过指定变量名来修改变量了.

Python中实现输入超时及如何通过变量获取变量名

通过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中实现输入超时及如何通过变量获取变量的名字,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
python使用urllib模块和pyquery实现阿里巴巴排名查询
Jan 16 Python
python实现倒计时的示例
Feb 14 Python
从零学python系列之从文件读取和保存数据
May 23 Python
Python中字符串的格式化方法小结
May 03 Python
Python 类与元类的深度挖掘 I【经验】
May 06 Python
Python在不同目录下导入模块的实现方法
Oct 27 Python
python编程线性回归代码示例
Dec 07 Python
python使用 zip 同时迭代多个序列示例
Jul 06 Python
python实现的接收邮件功能示例【基于网易POP3服务器】
Sep 11 Python
利用Python自动化操作AutoCAD的实现
Apr 01 Python
python 实现图片修复(可用于去水印)
Nov 19 Python
写好Python代码的几条重要技巧
May 21 Python
Pytorch 计算误判率,计算准确率,计算召回率的例子
Jan 18 #Python
python:目标检测模型预测准确度计算方式(基于IoU)
Jan 18 #Python
Python实现计算长方形面积(带参数函数demo)
Jan 18 #Python
python实现的Iou与Giou代码
Jan 18 #Python
Python 简单计算要求形状面积的实例
Jan 18 #Python
python实现用类读取文件数据并计算矩形面积
Jan 18 #Python
python不使用for计算两组、多个矩形两两间的iou方式
Jan 18 #Python
You might like
php+mysql事务rollback&commit示例
2010/02/08 PHP
PHP求小于1000的所有水仙花数的代码
2012/01/10 PHP
一个简洁的PHP可逆加密函数(分享)
2013/06/06 PHP
php实现利用phpexcel导出数据
2013/08/24 PHP
ThinkPHP函数详解之M方法和R方法
2015/09/10 PHP
PHP图形计数器程序显示网站用户浏览量
2016/07/20 PHP
ThinkPHP框架实现数据增删改
2017/05/07 PHP
php 人员权限管理(RBAC)实例(推荐)
2017/05/24 PHP
遨游,飞飞,IE,空中网 浏览器无提示关闭方法
2011/07/11 Javascript
Javascript中prototype属性实现给内置对象添加新的方法
2015/05/14 Javascript
js微信支付实现代码
2016/12/22 Javascript
JavaScript实现的商品抢购倒计时功能示例
2017/04/17 Javascript
JavaScript取得gridview中获取checkbox选中的值
2017/07/24 Javascript
利用JS实现scroll自定义滚动效果详解
2017/10/17 Javascript
vue 项目如何引入微信sdk接口的方法
2017/12/18 Javascript
使用vue-aplayer插件时出现的问题的解决
2018/03/02 Javascript
对VUE中的对象添加属性
2018/09/18 Javascript
vue 项目地址去掉 #的方法
2018/10/20 Javascript
vue webpack打包后图片路径错误的完美解决方法
2018/12/07 Javascript
js实现旋转木马轮播图效果
2020/01/10 Javascript
openlayers实现地图测距测面
2020/09/25 Javascript
[06:42]DOTA2每周TOP10 精彩击杀集锦vol.1
2014/06/25 DOTA
[04:29]2016国际邀请赛中国区预选赛Ehome战队教练采访
2016/06/27 DOTA
浅谈Python基础之I/O模型
2017/05/11 Python
django 多数据库配置教程
2018/05/30 Python
python创造虚拟环境方法总结
2019/03/04 Python
python科学计算之narray对象用法
2019/11/25 Python
pytorch中的transforms模块实例详解
2019/12/31 Python
linux 下python多线程递归复制文件夹及文件夹中的文件
2020/01/02 Python
python中把元组转换为namedtuple方法
2020/12/09 Python
HTML5 canvas基本绘图之绘制线段
2016/06/27 HTML / CSS
家得宝官网:The Home Depot(全球最大的家居装饰专业零售商)
2018/12/17 全球购物
大学考试作弊检讨书
2014/01/30 职场文书
企业军训感想
2014/02/07 职场文书
优秀党员申报材料
2014/12/18 职场文书
小学生节水倡议书
2015/04/29 职场文书