python 方法无法在线程中使用(附python获取网络流量)
在python中,定义一个方法,直接调用可以,但是创建一个线程来调用就可能导致失败。这种现象多出现在使用com对象进行系统操作时,而且是以线程的形式调用。
异常提示如下:syntax error。WMI returned a syntax error: you're probably running inside a thread without first calling pythoncom.CoInitialize[Ex] (no underlying exception)
仔细观察的话,异常提示中已经给出了解决方案。在运行一个线程的时候需要调用pythoncom.CoInitialize()方法。鄙人在程序中使用了WMI模块,试图获取部分系统信息。
异常的原因(推测)是com的机制问题。由于COM机制允许任意两组件之间相互通信而不必关心是在何种计算机上的何种操作系统下运行,也不用关心组件是使用何种语言编制的,这使COM技术拥有了强大的生命力。初始化COM环境的目的是使调用COM的API工作正常,也就是在COM操作之前调用CoInitialize或CoInitializeEX所以在线程函数中,如果使用com对象就必须调用CoInitialize或CoInitializeEX ,同时在退出时使用CoUninitialize来释放对象。
案例:
c = wmi.WMI()
interfaces = c.Win32_PerfRawData_Tcpip_NetworkInterface()
print len(interfaces)
rec = send = 0.0
for t in interfaces:
print t.Name
rec += float(t.BytesReceivedPersec) / 1024 / 1024
send += float(t.BytesSentPersec) / 1024 / 1024
print rec, send
这段代码是根据电脑的网卡获取上下行的流量(即发送流量和接收流量),直接运行是可以的。但是在tornado的RequestHandler的get或者post方法中使用时,会抛出异常syntax error及相关提示。在RequestHandler中,post或者get请求被认为是一个后台的线程方法,所以需要在实例化WMI这个com组件之前先进行com实例化。
为什么RequestHandler中post或者get请求被认为是一个后台的线程方法?这个问题从使用tornado的代码中可以窥得一二。代码如下:
if __name__ == '__main__':
app = tornado.web.Application(
handlers=[(r"/test/(\w+)", testHandler),
(r'/', MainHandler)]
)
server = tornado.httpserver.HTTPServer(app)
server = server.listen(8848)
tornado.ioloop.IOLoop.instance().start();
在给tornado配置了路由规则之后,我们开启了httpserver的服务,最后创建进程来使tornado运行起来。而每次的post或者get请求则是通过路由调用相应的Handler,这些都是在线程中执行的。故案例中通过com组件WMI来获取系统流量放在get方法中就会报错。修改后如下:
def get(self):
res = {}
pythoncom.CoInitialize()
c = wmi.WMI()
interfaces = c.Win32_PerfRawData_Tcpip_NetworkInterface()
print len(interfaces)
rec = send = 0.0
for t in interfaces:
print t.Name
rec += float(t.BytesReceivedPersec) / 1024 / 1024
send += float(t.BytesSentPersec) / 1024 / 1024
print rec, send
res["receive"] = "%.2f" % rec
res["send"] = "%.2f" % send
self._write_json(res)
关于WMI模块的使用可以参考如下:http://wutils.com/wmi/root/cimv2/win32_perfrawdata_tcpip_networkinterface/ 模块中很有很多类型(类型也有很多属性),在具体使用的过程中查询起来很痛苦。案例中的统计流量用的是Win32_PerfRawData_Tcpip_NetworkInterface ,也有解决方案用的是Win32_PerfRawData_Tcpip_TCPv4 两个统计到的数据差别很大,请根据实际情况来选择。
关于com机制的资料参考自:http://blog.csdn.net/chenglingsu6/article/details/5999134
python 方法无法在线程中使用(附python获取网络流量)的更多相关文章
- Python并发编程之线程中的信息隔离(五)
大家好,并发编程 进入第三篇. 上班第一天,大家应该比较忙吧.小明也是呢,所以今天的内容也很少.只要几分钟就能学完. 昨天我们说,线程与线程之间要通过消息通信来控制程序的执行. 讲完了消息通信,今天就 ...
- 用Handler的post()方法来传递线程中的代码段到主线程中执行
自定义的线程中是不能更新UI的,但是如果遇到更新UI的事情,我们可以用handler的post()方法来将更新UI的方法体,直接传送到主线程中,这样就能直接更新UI了.Handler的post()方法 ...
- Python爆火的原因与未来|内附Python学习书籍大礼包无偿领取|
从12年到20年,python以肉眼可见的趋势超过了java,成为了当今It界人人皆知的编程语言. python为什么这么火? 网络编程语言搜索指数 适合初学者 Python具有语法简单.语句清晰的特 ...
- Java Spring 在线程中或其他位置获取 ApplicationContext 或 ServiceBean
部分一转载自:http://blog.csdn.net/yang123111/article/details/32099329 via @yang123111 部分二转载自:http://www.cn ...
- C#中调用python方法
最近因为项目设计,有部分使用Python脚本,因此代码中需要调用python方法. 1.首先,在c#中调用python必须安装IronPython,在 http://ironpython.codepl ...
- (转)Android在子线程中更新Activity中UI的方法
转:http://blog.sina.com.cn/s/blog_3fe961ae0100mvc5.html 在Android平台下,进行多线程编程时,经常需要在主线程之外的一个单独的线程中进行某些处 ...
- Android--Handler的用法:在子线程中更新界面
本文主要介绍Android的Handler的用法.Handler能够发送Messsage和Runnable对象到与其相关联的线程的消息队列. 每一个Handler对象与创建它的线程相关联.而且每一个H ...
- Android中高效的显示图片之二——在非UI线程中处理图片
在“加载大图”文章中提到的BitmapFactory.decode*方法,如果源数据是在磁盘.网络或其它任何不是在内存中的位置,那么它都不应该在UI线程中执行.因为它的加载时间不可预测且依赖于一系列因 ...
- 使用Handler在子线程中更新UI
Android规定仅仅能在主线程中更新UI.假设在子线程中更新UI 的话会提演示样例如以下错误:Only the original thread that created a view hierach ...
随机推荐
- Android检测网络是否可用并获取网络类型
在类中使用getSystemService的时候需要这样进行使用:1. public class JajaMenu extends Activity { public static JajaMenu ...
- Python 图像处理: 生成二维高斯分布蒙版
在图像处理以及图像特效中,经常会用到一种成高斯分布的蒙版,蒙版可以用来做图像融合,将不同内容的两张图像结合蒙版,可以营造不同的艺术效果. I=M∗F+(1−M)∗B 这里I 表示合成后的图像,F 表示 ...
- Windows 10 子系统Linux重启(不重启Win10)
Using CMD (Administrator) net stop LxssManager net start LxssManager
- 1 开始ThreeJs
因为需要 需要一款 网页上的 游戏引擎 通过百度知道了 three.js 1.先从github上clone下源码 https://github.com/mrdoob/three.js 2.下载web ...
- 在WPF中制作正圆形公章
原文:在WPF中制作正圆形公章 之前,我利用C#与GDI+程序制作过正圆形公章(利用C#制作公章 ,C#制作公章[续])并将它集成到一个小软件中(个性印章及公章的画法及实现),今天我们来探讨一下WPF ...
- HDU 1867 A + B for you again KMP解决问题的方法
这是一个典型问题KMP申请书. 结果求增加两个字符串.该法的总和是相同的前缀和后缀也是字符串的字符串,您将可以合并本节. 但是,这个问题是不是问题非常明确的含义,因为不是太清楚,外观这两个字符串的顺序 ...
- SICP 锻炼 (1.40)解决摘要
SICP 锻炼1.40 是一个休闲的工作非常easy,但它看起来很复杂,单的一道题. 题目原题例如以下: 请定义一个过程cubic, 它和newtons-method过程一起使用在以下形式的表达式里: ...
- HDU 2845 Beans(dp)
Problem Description Bean-eating is an interesting game, everyone owns an M*N matrix, which is filled ...
- HQL链接查询
和SQL查询一样,HQL也支持各种各样的连接查询,如内连接.外连接.我们知道在SQL中可通过join字句实现多表之间的连接查询.HQL同样提供了连接查询机制,还允许显示指定迫切内连接和迫切左外连接.H ...
- DELPHI下多线程编程的几个思维误区(QDAC)
有几个网友私下问我一些有关线程的事情.过节写个东西上来大家交流. 思维误区1,自己新建的THREAD是线程,自己的主程序不是线程. 很多人在多线程编程没有把主线程也当作线程.其实主线程也是线程.看起来 ...