﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-魔のkyo的工作室-随笔分类-Python</title><link>http://cnitblog.com/luckydmz/category/8973.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 25 Aug 2021 18:39:45 GMT</lastBuildDate><pubDate>Wed, 25 Aug 2021 18:39:45 GMT</pubDate><ttl>60</ttl><item><title>解决matplotlib中文乱码</title><link>http://www.cnitblog.com/luckydmz/archive/2021/08/25/92493.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Wed, 25 Aug 2021 09:25:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2021/08/25/92493.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92493.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2021/08/25/92493.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92493.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92493.html</trackback:ping><description><![CDATA[<div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">import</span>&nbsp;matplotlib.pyplot&nbsp;as&nbsp;plt<br />plt.rcParams[<span style="color: #800000; ">"</span><span style="color: #800000; ">font.sans-serif</span><span style="color: #800000; ">"</span>]=[<span style="color: #800000; ">"</span><span style="color: #800000; ">SimHei</span><span style="color: #800000; ">"</span>]<br />plt.rcParams[<span style="color: #800000; ">"</span><span style="color: #800000; ">axes.unicode_minus</span><span style="color: #800000; ">"</span>]=False</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92493.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2021-08-25 17:25 <a href="http://www.cnitblog.com/luckydmz/archive/2021/08/25/92493.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python实现滚动数组，Python特殊方法的使用，Python运算符重载</title><link>http://www.cnitblog.com/luckydmz/archive/2020/09/07/92340.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Mon, 07 Sep 2020 07:48:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2020/09/07/92340.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92340.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2020/09/07/92340.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92340.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92340.html</trackback:ping><description><![CDATA[<div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;-*-&nbsp;coding:&nbsp;utf-8&nbsp;-*-</span><span style="color: #008000; "><br /></span><br /><span style="color: #0000FF; ">class</span>&nbsp;RollArray:<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;Iterator:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__init__</span>(self,&nbsp;subject):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.subject&nbsp;=&nbsp;subject<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.start&nbsp;=&nbsp;self.subject.idx<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.i&nbsp;=&nbsp;0<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__next__</span>(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;self.i&nbsp;&lt;&nbsp;self.subject.capability:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.start&nbsp;+&nbsp;self.i&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;self.subject:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;o&nbsp;=&nbsp;self.subject[self.start&nbsp;+&nbsp;self.i]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.i&nbsp;+=&nbsp;1<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;o<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.i&nbsp;+=&nbsp;1<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">raise</span>&nbsp;StopIteration()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__init__</span>(self,&nbsp;capability,&nbsp;items=[]):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.data&nbsp;=&nbsp;[None]&nbsp;*&nbsp;capability<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.used&nbsp;=&nbsp;[False]&nbsp;*&nbsp;capability<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.idx&nbsp;=&nbsp;0<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.capability&nbsp;=&nbsp;capability<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;e&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;items:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.append(e)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;append(self,&nbsp;obj):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.data[self.idx]&nbsp;=&nbsp;obj<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.used[self.idx]&nbsp;=&nbsp;True<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.idx&nbsp;=&nbsp;(self.idx&nbsp;+&nbsp;1)&nbsp;%&nbsp;10<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;重载&nbsp;for&nbsp;e&nbsp;in&nbsp;x:</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__iter__</span>(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;RollArray.Iterator(self)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;重载&nbsp;[]&nbsp;const</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__getitem__</span>(self,&nbsp;i):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.used[i%self.capability]:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;self.data[i%self.capability]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">raise</span>&nbsp;IndexError()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;重载&nbsp;[]</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__setitem__</span>(self,&nbsp;i,&nbsp;v):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.data[i%self.capability]&nbsp;=&nbsp;v<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.used[i%self.capability]&nbsp;=&nbsp;True<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;v<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;重载&nbsp;del&nbsp;x[]</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__delitem__</span>(self,&nbsp;i):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.used[i%self.capability]&nbsp;=&nbsp;False<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;重载&nbsp;if&nbsp;e&nbsp;in&nbsp;x:</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__contains__</span>(self,&nbsp;i):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;self.used[i%self.capability]<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;tolist(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l&nbsp;=&nbsp;[]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;e&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;self:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l.append(e)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;l<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__repr__</span>(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;f<span style="color: #800000; ">"</span><span style="color: #800000; ">{self.__class__.__name__}({self.capability},&nbsp;items={self.tolist()})</span><span style="color: #800000; ">"</span><br /><br /><br /><span style="color: #0000FF; ">if</span>&nbsp;<span style="color: #800080; ">__name__</span>&nbsp;==&nbsp;<span style="color: #800000; ">'</span><span style="color: #800000; ">__main__</span><span style="color: #800000; ">'</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;arr&nbsp;=&nbsp;RollArray(10,&nbsp;range(5))<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">del</span>&nbsp;arr[3]<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">print</span>(arr)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;i&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;range(5,&nbsp;11):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr.append(i)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">print</span>(arr)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;arr[11]&nbsp;=&nbsp;11<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">print</span>(arr)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;e&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;arr:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">print</span>(e)</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92340.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2020-09-07 15:48 <a href="http://www.cnitblog.com/luckydmz/archive/2020/09/07/92340.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用flask和flask_restful搭建Restful Web Service的模板</title><link>http://www.cnitblog.com/luckydmz/archive/2020/03/25/92122.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Wed, 25 Mar 2020 10:51:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2020/03/25/92122.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92122.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2020/03/25/92122.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92122.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92122.html</trackback:ping><description><![CDATA[<br /><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;-*-&nbsp;coding:&nbsp;utf-8&nbsp;-*-</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">import</span>&nbsp;datetime<br /><span style="color: #0000FF; ">import</span>&nbsp;time<br /><span style="color: #0000FF; ">from</span>&nbsp;flask&nbsp;<span style="color: #0000FF; ">import</span>&nbsp;Flask&nbsp;as&nbsp;_Flask<br /><span style="color: #0000FF; ">from</span>&nbsp;flask&nbsp;<span style="color: #0000FF; ">import</span>&nbsp;request,&nbsp;jsonify&nbsp;as&nbsp;_jsonify<br /><span style="color: #0000FF; ">from</span>&nbsp;flask.json&nbsp;<span style="color: #0000FF; ">import</span>&nbsp;JSONEncoder&nbsp;as&nbsp;_JSONEncoder<br /><span style="color: #0000FF; ">from</span>&nbsp;flask_restful&nbsp;<span style="color: #0000FF; ">import</span>&nbsp;Api,&nbsp;Resource<br /><br /><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;处理自定义数据类型的JSON编码</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">class</span>&nbsp;JSONEncoder(_JSONEncoder):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;default(self,&nbsp;o):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;hasattr(o,&nbsp;<span style="color: #800000; ">'</span><span style="color: #800000; ">keys</span><span style="color: #800000; ">'</span>)&nbsp;<span style="color: #0000FF; ">and</span>&nbsp;hasattr(o,&nbsp;<span style="color: #800000; ">'</span><span style="color: #800000; ">__getitem__</span><span style="color: #800000; ">'</span>):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;dict(o)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;isinstance(o,&nbsp;datetime.datetime):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;o.strftime(<span style="color: #800000; ">'</span><span style="color: #800000; ">%Y-%m-%d&nbsp;%H:%M:%S</span><span style="color: #800000; ">'</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;isinstance(o,&nbsp;datetime.date):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;o.strftime(<span style="color: #800000; ">'</span><span style="color: #800000; ">%Y-%m-%d</span><span style="color: #800000; ">'</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;isinstance(o,&nbsp;datetime.time):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;o.strftime(<span style="color: #800000; ">'</span><span style="color: #800000; ">%H:%M:%S</span><span style="color: #800000; ">'</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;isinstance(o,&nbsp;Exception):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;str(o)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;super(JSONEncoder,&nbsp;self).default(o)<br /><br /><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;改进jsonify，支持传入HTTP状态码和HTTP头</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">def</span>&nbsp;jsonify(data_or_tuple,&nbsp;status_code=None,&nbsp;headers=None):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;type(data_or_tuple)&nbsp;==&nbsp;tuple&nbsp;<span style="color: #0000FF; ">and</span>&nbsp;<span style="color: #0000FF; ">not</span>&nbsp;status_code&nbsp;<span style="color: #0000FF; ">and</span>&nbsp;<span style="color: #0000FF; ">not</span>&nbsp;headers:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;jsonify(*data_or_tuple)<br />&nbsp;&nbsp;&nbsp;&nbsp;rsp&nbsp;=&nbsp;_jsonify(data_or_tuple)<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;status_code:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rsp.status_code&nbsp;=&nbsp;status_code<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;headers:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;k,&nbsp;v&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;headers.items():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rsp.headers[k]&nbsp;=&nbsp;v<br />&nbsp;&nbsp;&nbsp;&nbsp;rsp.headers[<span style="color: #800000; ">"</span><span style="color: #800000; ">Access-Control-Allow-Origin</span><span style="color: #800000; ">"</span>]&nbsp;=&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">*</span><span style="color: #800000; ">"</span>&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;允许跨域访问</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;rsp<br /><br /><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;继承原始的Flask为了替换其中的JSONEncoder</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">class</span>&nbsp;Flask(_Flask):<br />&nbsp;&nbsp;&nbsp;&nbsp;json_encoder&nbsp;=&nbsp;JSONEncoder<br /><br /><br />app&nbsp;=&nbsp;Flask(<span style="color: #800080; ">__name__</span>)<br />app.config[<span style="color: #800000; ">'</span><span style="color: #800000; ">JSON_SORT_KEYS</span><span style="color: #800000; ">'</span>]&nbsp;=&nbsp;False&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;关闭返回JSON数据时根据KEY的字母序重新排序</span><span style="color: #008000; "><br /></span>api&nbsp;=&nbsp;Api(app)<br /><br /><br /><span style="color: #0000FF; ">class</span>&nbsp;IndexResource(Resource):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;get(self):&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;方法名即http&nbsp;method</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;obj&nbsp;=&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">str</span><span style="color: #800000; ">"</span>:&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">Hello&nbsp;world.</span><span style="color: #800000; ">"</span>,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">now</span><span style="color: #800000; ">"</span>:&nbsp;datetime.datetime.now()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;jsonify({<span style="color: #800000; ">"</span><span style="color: #800000; ">result_code</span><span style="color: #800000; ">"</span>:&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">success</span><span style="color: #800000; ">"</span>,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">data</span><span style="color: #800000; ">"</span>:&nbsp;obj},&nbsp;200)<br />api.add_resource(IndexResource,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">/</span><span style="color: #800000; ">"</span>)&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;绑定主页URL到IndexResource类</span><span style="color: #008000; "><br /></span><br /><br /><span style="color: #0000FF; ">class</span>&nbsp;UserResource(Resource):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;get(self,&nbsp;name):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;1&nbsp;&lt;=&nbsp;len(name)&nbsp;&lt;=&nbsp;10:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;obj&nbsp;=&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">str</span><span style="color: #800000; ">"</span>:&nbsp;f<span style="color: #800000; ">"</span><span style="color: #800000; ">Hello,&nbsp;{name}.</span><span style="color: #800000; ">"</span>,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">now</span><span style="color: #800000; ">"</span>:&nbsp;datetime.datetime.now()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;jsonify({<span style="color: #800000; ">"</span><span style="color: #800000; ">result_code</span><span style="color: #800000; ">"</span>:&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">success</span><span style="color: #800000; ">"</span>,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">data</span><span style="color: #800000; ">"</span>:&nbsp;obj},&nbsp;200)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;jsonify({<span style="color: #800000; ">"</span><span style="color: #800000; ">result_code</span><span style="color: #800000; ">"</span>:&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">fail</span><span style="color: #800000; ">"</span>,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">err_code</span><span style="color: #800000; ">"</span>:&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">INVALID_PARAM</span><span style="color: #800000; ">"</span>,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">err_code_des</span><span style="color: #800000; ">"</span>:&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">name非法</span><span style="color: #800000; ">"</span>},&nbsp;401)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;put(self,&nbsp;name):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">pass</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;delete(self,&nbsp;name):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">pass</span><br /><br />api.add_resource(UserResource,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">/users/&lt;name&gt;</span><span style="color: #800000; ">"</span>)<br /><br /><span style="color: #0000FF; ">class</span>&nbsp;UsersResource(Resource):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;使用&nbsp;http://127.0.0.1:30101/users/&nbsp;POST&nbsp;访问</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;RequestBody:&nbsp;{"name":"daimingzhuang"}</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;记得添加header:&nbsp;Content-Type&nbsp;:&nbsp;application/json</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;post(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;body_obj&nbsp;=&nbsp;request.get_json()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">print</span>(body_obj)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;jsonify({<span style="color: #800000; ">"</span><span style="color: #800000; ">result_code</span><span style="color: #800000; ">"</span>:&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">success</span><span style="color: #800000; ">"</span>,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">data</span><span style="color: #800000; ">"</span>:&nbsp;body_obj},&nbsp;200)<br />api.add_resource(UsersResource,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">/users/</span><span style="color: #800000; ">"</span>)<br /><br /><br /><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;生产环境通过gunicorn启动</span><span style="color: #008000; "><br />#</span><span style="color: #008000; ">&nbsp;使用&nbsp;pip3&nbsp;install&nbsp;gunicorn&nbsp;安装&nbsp;gunicorn</span><span style="color: #008000; "><br />#</span><span style="color: #008000; ">&nbsp;gunicorn&nbsp;-b&nbsp;&lt;bind_ip&gt;:&lt;port&gt;&nbsp;&lt;filename&gt;:&lt;Flask&nbsp;app&nbsp;object&gt;</span><span style="color: #008000; "><br />#</span><span style="color: #008000; ">&nbsp;例如:&nbsp;gunicorn&nbsp;-b&nbsp;0.0.0.0:30101&nbsp;app:app</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">if</span>&nbsp;<span style="color: #800080; ">__name__</span>&nbsp;==&nbsp;<span style="color: #800000; ">'</span><span style="color: #800000; ">__main__</span><span style="color: #800000; ">'</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;SERVER_PORT&nbsp;=&nbsp;30101<br />&nbsp;&nbsp;&nbsp;&nbsp;app.run(debug=True,&nbsp;host=<span style="color: #800000; ">'</span><span style="color: #800000; ">0.0.0.0</span><span style="color: #800000; ">'</span>,&nbsp;port=SERVER_PORT)</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92122.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2020-03-25 18:51 <a href="http://www.cnitblog.com/luckydmz/archive/2020/03/25/92122.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python中监视线程卡死并自动崩溃退出 WatchDog</title><link>http://www.cnitblog.com/luckydmz/archive/2020/03/17/92113.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Tue, 17 Mar 2020 07:32:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2020/03/17/92113.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92113.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2020/03/17/92113.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92113.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92113.html</trackback:ping><description><![CDATA[监视主线程卡死，发现时进行处理，例如保错再主动崩溃退出，这样再结合监视崩溃自动重启就可以在卡死时实现自动重启。<br /><br /><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">import</span>&nbsp;threading<br /><span style="color: #0000FF; ">import</span>&nbsp;traceback<br /><span style="color: #0000FF; ">import</span>&nbsp;time<br /><span style="color: #0000FF; ">import</span>&nbsp;sys<br /><span style="color: #0000FF; ">import</span>&nbsp;os<br /><span style="color: #0000FF; ">from</span>&nbsp;functools&nbsp;<span style="color: #0000FF; ">import</span>&nbsp;wraps<br /><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;from&nbsp;.logger&nbsp;import&nbsp;logger</span><span style="color: #008000; "><br /></span><br /><span style="color: #0000FF; ">class</span>&nbsp;WatchDog(threading.Thread):<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__init__</span>(self,&nbsp;timeout=10,&nbsp;echo=False):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(WatchDog,&nbsp;self).<span style="color: #800080; ">__init__</span>()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.timeout&nbsp;=&nbsp;timeout<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.echo&nbsp;=&nbsp;echo<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.last_kicked_ts&nbsp;=&nbsp;time.time()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.lock&nbsp;=&nbsp;threading.Lock()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.thread_id&nbsp;=&nbsp;threading.currentThread().ident<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.terminated&nbsp;=&nbsp;False<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.setDaemon(True)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.start()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;terminate(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.terminated&nbsp;=&nbsp;True<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.join(self.timeout)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;kick(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.lock.acquire()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.last_kicked_ts&nbsp;=&nbsp;time.time()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.lock.release()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;bark(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;formated_frame_stack&nbsp;=&nbsp;self._get_formated_frame_stack()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.echo:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">print</span>(<span style="color: #800000; ">"</span><span style="color: #800000; ">!!!!!&nbsp;WATCH&nbsp;DOG&nbsp;FAILURE&nbsp;TRIGGERED&nbsp;!!!!!\n</span><span style="color: #800000; ">"</span>&nbsp;+&nbsp;formated_frame_stack)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;logger.fatal("!!!!!&nbsp;WATCH&nbsp;DOG&nbsp;FAILURE&nbsp;TRIGGERED&nbsp;!!!!!\n"&nbsp;+&nbsp;formated_frame_stack)</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pid&nbsp;=&nbsp;os.getpid()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os.kill(pid,&nbsp;2)&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;通知进程退出</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(5)&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;等待5秒</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os.kill(pid,&nbsp;9)&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;发送强制退出</span><span style="color: #008000; "><br /></span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;run(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;<span style="color: #0000FF; ">not</span>&nbsp;self.terminated:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ts&nbsp;=&nbsp;time.time()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.lock.acquire()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is_timeout&nbsp;=&nbsp;ts&nbsp;-&nbsp;self.last_kicked_ts&nbsp;&gt;&nbsp;self.timeout<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.lock.release()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;is_timeout:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.bark()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n&nbsp;=&nbsp;int(max(self.timeout&nbsp;/&nbsp;3,&nbsp;1))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;i&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;range(n*10):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(0.1)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.terminated:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">break</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;@staticmethod<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;_get_thread(tid):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;t&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;threading.enumerate():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;t.ident&nbsp;==&nbsp;tid:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;t<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;None<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;@staticmethod<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;_get_frame_stack(tid):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;thread_id,&nbsp;stack&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;sys._current_frames().items():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;thread_id&nbsp;==&nbsp;tid:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;stack<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;None<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;_get_formated_frame_stack(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info&nbsp;=&nbsp;[]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;th&nbsp;=&nbsp;self._get_thread(self.thread_id)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack&nbsp;=&nbsp;self._get_frame_stack(self.thread_id)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info.append(<span style="color: #800000; ">'</span><span style="color: #800000; ">%s&nbsp;thead_id=%d</span><span style="color: #800000; ">'</span>&nbsp;%&nbsp;(th.name,&nbsp;self.thread_id))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;filename,&nbsp;lineno,&nbsp;_,&nbsp;line&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;traceback.extract_stack(stack):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info.append(<span style="color: #800000; ">'</span><span style="color: #800000; ">&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;%s(%s:%d)</span><span style="color: #800000; ">'</span>&nbsp;%&nbsp;(line,&nbsp;filename[filename.rfind(os.path.sep)&nbsp;+&nbsp;1:],&nbsp;lineno))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #800000; ">'</span><span style="color: #800000; ">\n</span><span style="color: #800000; ">'</span>.join(info)<br /><br /><br /><span style="color: #0000FF; ">def</span>&nbsp;watch_dog(timeout=10,&nbsp;echo=False):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;inner(func):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;wrapper(*args,&nbsp;**kw):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dog&nbsp;=&nbsp;WatchDog(timeout=timeout,&nbsp;echo=echo)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;=&nbsp;func(*args,&nbsp;**kw)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dog.terminate()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;ret<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;wrapper<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;inner</div><br />用法：<br /><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><br />dog&nbsp;=&nbsp;WatchDog(echo=True)<br /><span style="color: #0000FF; ">while</span>&nbsp;True:<br />&nbsp;&nbsp;&nbsp;&nbsp;consumer.workex(timeout_ms=100)<br />&nbsp;&nbsp;&nbsp;&nbsp;dog.kick()</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92113.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2020-03-17 15:32 <a href="http://www.cnitblog.com/luckydmz/archive/2020/03/17/92113.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解决pandas打印DataFrame显示不全</title><link>http://www.cnitblog.com/luckydmz/archive/2020/02/24/92066.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Mon, 24 Feb 2020 12:27:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2020/02/24/92066.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92066.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2020/02/24/92066.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92066.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92066.html</trackback:ping><description><![CDATA[<br /><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">def</span>&nbsp;float_format(x):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;abs(x)&nbsp;&gt;=&nbsp;1e10&nbsp;<span style="color: #0000FF; ">or</span>&nbsp;0&nbsp;&lt;&nbsp;abs(x)&nbsp;&lt;&nbsp;1e-3:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">%e</span><span style="color: #800000; ">"</span>&nbsp;%&nbsp;x<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">%.4f</span><span style="color: #800000; ">"</span>&nbsp;%&nbsp;x<br /><br /><br /><span style="color: #0000FF; ">def</span>&nbsp;pandas_pretty_printing():<br />&nbsp;&nbsp;&nbsp;&nbsp;pd.set_option(<span style="color: #800000; ">'</span><span style="color: #800000; ">display.max_rows</span><span style="color: #800000; ">'</span>,&nbsp;None)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;解决行显示不全</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;pd.set_option(<span style="color: #800000; ">'</span><span style="color: #800000; ">display.max_columns</span><span style="color: #800000; ">'</span>,&nbsp;None)&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;解决列显示不全</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;pd.set_option(<span style="color: #800000; ">'</span><span style="color: #800000; ">max_colwidth</span><span style="color: #800000; ">'</span>,&nbsp;1000)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;解决列宽不够</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;pd.set_option(<span style="color: #800000; ">'</span><span style="color: #800000; ">display.width</span><span style="color: #800000; ">'</span>,&nbsp;1000)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;解决列过早换行</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;pd.set_option(<span style="color: #800000; ">'</span><span style="color: #800000; ">display.float_format</span><span style="color: #800000; ">'</span>,&nbsp;float_format)&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;解决浮点数总是科学计数法</span></div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92066.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2020-02-24 20:27 <a href="http://www.cnitblog.com/luckydmz/archive/2020/02/24/92066.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python实现的一个消息总线+计划任务 Driver</title><link>http://www.cnitblog.com/luckydmz/archive/2020/01/21/92025.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Tue, 21 Jan 2020 06:28:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2020/01/21/92025.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92025.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2020/01/21/92025.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92025.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92025.html</trackback:ping><description><![CDATA[<div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><br /><span style="color: #0000FF; ">import</span>&nbsp;threading<br /><span style="color: #0000FF; ">import</span>&nbsp;time<br /><span style="color: #0000FF; ">import</span>&nbsp;queue<br /><span style="color: #0000FF; ">from</span>&nbsp;dataclasses&nbsp;<span style="color: #0000FF; ">import</span>&nbsp;dataclass,&nbsp;field<br /><span style="color: #0000FF; ">from</span>&nbsp;typing&nbsp;<span style="color: #0000FF; ">import</span>&nbsp;Any<br /><br />@dataclass(order=True)<br /><span style="color: #0000FF; ">class</span>&nbsp;ScheduledItem:<br />&nbsp;&nbsp;&nbsp;&nbsp;time_sec:&nbsp;float<br />&nbsp;&nbsp;&nbsp;&nbsp;cb:&nbsp;Any&nbsp;=&nbsp;field(compare=False)<br /><br /><span style="color: #0000FF; ">class</span>&nbsp;Driver:<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__init__</span>(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.scheduled&nbsp;=&nbsp;queue.PriorityQueue()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.scheduled_every_lock&nbsp;=&nbsp;threading.Lock()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.scheduled_every&nbsp;=&nbsp;[]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.callbacks_lock&nbsp;=&nbsp;threading.Lock()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.callbacks&nbsp;=&nbsp;{}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.async_queue&nbsp;=&nbsp;queue.Queue()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.epoch_sec&nbsp;=&nbsp;time.time()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.last_epoch&nbsp;=&nbsp;None<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;得到driver内的当前时间秒数</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;get_epoch(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;self.epoch_sec<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;执行一趟主逻辑，一般放在主循环中执行</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;run(self,&nbsp;wait_sync_interval=0):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.epoch_sec&nbsp;=&nbsp;time.time()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.last_epoch&nbsp;<span style="color: #0000FF; ">is</span>&nbsp;<span style="color: #0000FF; ">not</span>&nbsp;None:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.epoch_sec&nbsp;-&nbsp;self.last_epoch&nbsp;&lt;&nbsp;wait_sync_interval:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t&nbsp;=&nbsp;wait_sync_interval&nbsp;-&nbsp;(self.epoch_sec&nbsp;-&nbsp;self.last_epoch)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(t)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.epoch_sec&nbsp;=&nbsp;time.time()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.last_epoch&nbsp;=&nbsp;self.epoch_sec<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self._do_async()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self._do_schedule()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self._do_schedule_every()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;计划单次定时任务</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;schedule(self,&nbsp;cb,&nbsp;time_sec):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.scheduled.put_nowait(&nbsp;ScheduledItem(time_sec,&nbsp;cb)&nbsp;)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;计划重复任务</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;schedule_every(self,&nbsp;cb,&nbsp;interval_sec):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.scheduled_every_lock.acquire()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.scheduled_every.append(&nbsp;{&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">next_sec</span><span style="color: #800000; ">"</span>:self.epoch_sec+interval_sec,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">interval</span><span style="color: #800000; ">"</span>:interval_sec,&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">cb</span><span style="color: #800000; ">"</span>:cb&nbsp;}&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.scheduled_every_lock.release()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;增加消息接收者</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;add_receiver(self,&nbsp;topic_or_type,&nbsp;cb):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.callbacks_lock.acquire()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;topic_or_type&nbsp;<span style="color: #0000FF; ">not</span>&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;self.callbacks:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.callbacks[topic_or_type]&nbsp;=&nbsp;set()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.callbacks[topic_or_type].add(cb)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.callbacks_lock.release()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;cb<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;删除消息接收者</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;remove_receiver(self,&nbsp;topic_or_type,&nbsp;cb):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.callbacks_lock.acquire()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;topic_or_type&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;self.callbacks:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;cb&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;self.callbacks[topic_or_type]:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.callbacks[topic_or_type].remove(cb)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.callbacks_lock.release()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;同步发送消息</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;send(self,&nbsp;obj,&nbsp;topic=None):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;topic&nbsp;==&nbsp;None:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;topic&nbsp;=&nbsp;type(obj)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cbs&nbsp;=&nbsp;[]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.callbacks_lock.acquire()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;topic&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;self.callbacks.keys():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cbs&nbsp;=&nbsp;list(self.callbacks[topic])<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.callbacks_lock.release()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;cb&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;cbs:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cb(obj)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;异步发送消息</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;send_async(self,&nbsp;obj,&nbsp;topic=None):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.async_queue.put_nowait(&nbsp;(obj,&nbsp;topic)&nbsp;)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;_do_async(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;<span style="color: #0000FF; ">not</span>&nbsp;self.async_queue.empty():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.send(*self.async_queue.get_nowait())<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;_do_schedule(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i&nbsp;=&nbsp;0<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;<span style="color: #0000FF; ">not</span>&nbsp;self.scheduled.empty():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item&nbsp;=&nbsp;self.scheduled.get_nowait()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;item.time_sec&nbsp;&gt;&nbsp;self.epoch_sec:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.scheduled.put_nowait(item)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">break</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item.cb(self.epoch_sec)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;_do_schedule_every(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cbs&nbsp;=&nbsp;[]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.scheduled_every_lock.acquire()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;o&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;self.scheduled_every:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;self.epoch_sec&nbsp;&gt;=&nbsp;o[<span style="color: #800000; ">"</span><span style="color: #800000; ">next_sec</span><span style="color: #800000; ">"</span>]:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cbs.append(o[<span style="color: #800000; ">"</span><span style="color: #800000; ">cb</span><span style="color: #800000; ">"</span>])<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;o[<span style="color: #800000; ">"</span><span style="color: #800000; ">next_sec</span><span style="color: #800000; ">"</span>]&nbsp;+=&nbsp;o[<span style="color: #800000; ">"</span><span style="color: #800000; ">interval</span><span style="color: #800000; ">"</span>]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.scheduled_every_lock.release()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;cb&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;cbs:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cb(self.epoch_sec)<br /><br /><br /><span style="color: #0000FF; ">def</span>&nbsp;bind(func,&nbsp;*args,&nbsp;**kw):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">lambda</span>&nbsp;*_args,&nbsp;**_kw:&nbsp;func(*args,&nbsp;*_args,&nbsp;**kw,&nbsp;**_kw)<br /><br /><br />driver&nbsp;=&nbsp;Driver()</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92025.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2020-01-21 14:28 <a href="http://www.cnitblog.com/luckydmz/archive/2020/01/21/92025.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于Redis的分布式Mutex, ReadWriteLock</title><link>http://www.cnitblog.com/luckydmz/archive/2020/01/15/92018.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Wed, 15 Jan 2020 05:39:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2020/01/15/92018.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92018.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2020/01/15/92018.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92018.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92018.html</trackback:ping><description><![CDATA[<div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;-*-&nbsp;coding:&nbsp;utf-8&nbsp;-*-</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">from</span>&nbsp;redis&nbsp;<span style="color: #0000FF; ">import</span>&nbsp;ConnectionPool<br /><span style="color: #0000FF; ">import</span>&nbsp;redis<br /><span style="color: #0000FF; ">import</span>&nbsp;time<br /><span style="color: #0000FF; ">import</span>&nbsp;uuid<br /><br />POOL&nbsp;=&nbsp;ConnectionPool(host=<span style="color: #800000; ">'</span><span style="color: #800000; ">127.0.0.1</span><span style="color: #800000; ">'</span>,&nbsp;max_connections=100)<br /><br /><span style="color: #0000FF; ">class</span>&nbsp;Redis(redis.Redis):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__init__</span>(self,&nbsp;host=None):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">global</span>&nbsp;POOL<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;POOL.connection_kwargs[<span style="color: #800000; ">"</span><span style="color: #800000; ">host</span><span style="color: #800000; ">"</span>]&nbsp;!=&nbsp;host:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;POOL&nbsp;=&nbsp;ConnectionPool(host=host,&nbsp;max_connections=100)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super().<span style="color: #800080; ">__init__</span>(connection_pool=POOL)<br /><br /><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;互斥锁</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">class</span>&nbsp;Mutex:<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__init__</span>(self,&nbsp;name,&nbsp;server=<span style="color: #800000; ">"</span><span style="color: #800000; ">127.0.0.1</span><span style="color: #800000; ">"</span>):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.name&nbsp;=&nbsp;name<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.key_name&nbsp;=&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">MUTEX_</span><span style="color: #800000; ">"</span>&nbsp;+&nbsp;name<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.id&nbsp;=&nbsp;uuid.uuid4().hex<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.redis&nbsp;=&nbsp;Redis(host=server)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;acquire(self,&nbsp;blocking=True,&nbsp;ex=30):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;=&nbsp;self.redis.set(self.key_name,&nbsp;self.id,&nbsp;ex=ex,&nbsp;nx=True)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;blocking:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;<span style="color: #0000FF; ">not</span>&nbsp;r:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(0.01)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;=&nbsp;self.redis.set(self.key_name,&nbsp;self.id,&nbsp;ex=ex,&nbsp;nx=True)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;r<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;release(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.acquired():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.redis.delete(self.key_name)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;acquired(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;=&nbsp;self.redis.get(self.key_name)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;r&nbsp;!=&nbsp;None&nbsp;<span style="color: #0000FF; ">and</span>&nbsp;r.decode()&nbsp;==&nbsp;str(self.id)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__enter__</span>(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.acquire()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__exit__</span>(self,&nbsp;exc_type,&nbsp;exc_value,&nbsp;exc_trackback):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.release()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;exc_value&nbsp;!=&nbsp;None:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">raise</span>&nbsp;exc_value<br /><br /><br /><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;读写锁</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">class</span>&nbsp;ReadWriteLock:<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__init__</span>(self,&nbsp;name,&nbsp;server=<span style="color: #800000; ">"</span><span style="color: #800000; ">127.0.0.1</span><span style="color: #800000; ">"</span>):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.name&nbsp;=&nbsp;name<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.server&nbsp;=&nbsp;server<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.rlock_name&nbsp;=&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">RLOCK_</span><span style="color: #800000; ">"</span>&nbsp;+&nbsp;name<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.wlock_name&nbsp;=&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">WLOCK_</span><span style="color: #800000; ">"</span>&nbsp;+&nbsp;name<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.id&nbsp;=&nbsp;uuid.uuid4().hex<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.redis&nbsp;=&nbsp;Redis(host=server)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.lock_type&nbsp;=&nbsp;None<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;read_lock(self,&nbsp;blocking=True,&nbsp;ex=30):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex&nbsp;=&nbsp;Mutex(self.name,&nbsp;self.server)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex.acquire()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wlock_locked&nbsp;=&nbsp;self.redis.get(self.wlock_name)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;wlock_locked:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;blocking:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;wlock_locked:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex.release()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(0.05)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex.acquire()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wlock_locked&nbsp;=&nbsp;self.redis.get(self.wlock_name)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;False<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pipeline&nbsp;=&nbsp;self.redis.pipeline()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;now&nbsp;=&nbsp;time.time()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pipeline.zremrangebyscore(self.rlock_name,&nbsp;0,&nbsp;int((now-ex)*1000)&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pipeline.zadd(self.rlock_name,&nbsp;{self.id:&nbsp;int(now*1000)}&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pipeline.expire(self.rlock_name,&nbsp;ex)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pipeline.execute()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.lock_type&nbsp;=&nbsp;<span style="color: #800000; ">'</span><span style="color: #800000; ">R</span><span style="color: #800000; ">'</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;True<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">except</span>&nbsp;Exception&nbsp;as&nbsp;e:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">raise</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">finally</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex.release()<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;write_lock(self,&nbsp;blocking=True,&nbsp;ex=30):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex&nbsp;=&nbsp;Mutex(self.name,&nbsp;self.server)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex.acquire()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.redis.zremrangebyscore(self.rlock_name,&nbsp;0,&nbsp;int((time.time()-ex)*1000)&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;=&nbsp;self.redis.zcard(self.rlock_name)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;r:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;blocking:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;r:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex.release()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(0.05)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex.acquire()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.redis.zremrangebyscore(self.rlock_name,&nbsp;0,&nbsp;int((time.time()-ex)*1000)&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;=&nbsp;self.redis.zcard(self.rlock_name)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;False<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;=&nbsp;self.redis.set(self.wlock_name,&nbsp;self.id,&nbsp;ex=ex,&nbsp;nx=True)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;blocking:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;<span style="color: #0000FF; ">not</span>&nbsp;r:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex.release()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(0.05)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex.acquire()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;=&nbsp;self.redis.set(self.wlock_name,&nbsp;self.id,&nbsp;ex=ex,&nbsp;nx=True)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;r:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.lock_type&nbsp;=&nbsp;<span style="color: #800000; ">'</span><span style="color: #800000; ">W</span><span style="color: #800000; ">'</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;r<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">except</span>&nbsp;Exception&nbsp;as&nbsp;e:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">raise</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">finally</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex.release()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;unlock(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.lock_type&nbsp;==&nbsp;<span style="color: #800000; ">'</span><span style="color: #800000; ">R</span><span style="color: #800000; ">'</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.redis.zrem(self.rlock_name,&nbsp;self.id)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.lock_type&nbsp;=&nbsp;None<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">elif</span>&nbsp;self.lock_type&nbsp;==&nbsp;<span style="color: #800000; ">'</span><span style="color: #800000; ">W</span><span style="color: #800000; ">'</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;=&nbsp;self.redis.get(self.wlock_name)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;r&nbsp;!=&nbsp;None&nbsp;<span style="color: #0000FF; ">and</span>&nbsp;r.decode()&nbsp;==&nbsp;str(self.id):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.redis.delete(self.wlock_name)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.lock_type&nbsp;=&nbsp;None</div>考虑了锁住后崩溃，解决方案是超时后自动结束。<br />考虑了未崩溃但是超时（这种情况首先考虑默认超时时间是否应该调整，或者程序是否需要调整锁住的代码分多次锁？）。<br />在这种异常情况发生时，可能产生一边释放了锁但还在访问，另一边加上了锁，记住这时异常情况，但我们要保证即使它发生了也尽量能正常工作下去，<br />对于确实存在访问冲突的那么是没办法的，该异常就异常好了，还有种情况是虽然加了锁，但是并没有访问冲突，其实程序可以正常下去，但是这里会发生什么呢？<br />对于A线程，手动加锁----------超时自动解锁|------------------------手动解锁|<br />对于B线程，-------------手动加锁-----------|（等到此加锁成功）------------|---------手动解锁<br />对于C线程，---------------------------------|------------手动加锁------------|（等到此加锁成功）<br />A线程因为超时自动解锁后虽然和B线程没有发生访问冲突，但是它解了B线程的锁，导致C线程加锁成功，而B线程实际还没解锁，这又制造了潜在的B线程和C线程的访问冲突。<br />所以手动解锁时应该判断下当前的锁是否是自己加的。<br />支持阻塞和非阻塞加锁，默认阻塞，非阻塞用法<br />if lock.acquire(blocking=False):<br />&nbsp; &nbsp; pass<br />判断加锁成功在做一些事，一些其他语言里命名为tryLock方法。<img src ="http://www.cnitblog.com/luckydmz/aggbug/92018.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2020-01-15 13:39 <a href="http://www.cnitblog.com/luckydmz/archive/2020/01/15/92018.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python SQLAlchemy的ORM模块用例，多数据库连接封装 </title><link>http://www.cnitblog.com/luckydmz/archive/2020/01/07/92009.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Tue, 07 Jan 2020 03:05:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2020/01/07/92009.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92009.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2020/01/07/92009.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92009.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92009.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: db.pyCode highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->#&nbsp;-*-&nbsp;coding:&nbsp;utf-8&nbsp;-*-from&nbsp;sqlalchemy&nbsp;import&nbsp;Table,&nbsp;Colu...&nbsp;&nbsp;<a href='http://www.cnitblog.com/luckydmz/archive/2020/01/07/92009.html'>阅读全文</a><img src ="http://www.cnitblog.com/luckydmz/aggbug/92009.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2020-01-07 11:05 <a href="http://www.cnitblog.com/luckydmz/archive/2020/01/07/92009.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python使用msgpack对任意单层POD类型class编解码</title><link>http://www.cnitblog.com/luckydmz/archive/2019/11/20/91959.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Tue, 19 Nov 2019 16:00:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2019/11/20/91959.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/91959.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2019/11/20/91959.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/91959.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/91959.html</trackback:ping><description><![CDATA[<div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;msgpack<br /><br /></span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;obj_dict_serializer(obj):<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;msgpack.dumps(vars(obj))<br /><br /></span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;obj_dict_deserializer(T):<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;deserializer(buf):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;obj&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;T()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dic&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;msgpack.unpackb(buf)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;k,v&nbsp;</span><span style="color: #0000FF; ">in</span><span style="color: #000000; ">&nbsp;dic.items():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;k&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;k.decode()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;type(v)</span><span style="color: #000000; ">==</span><span style="color: #000000; ">bytes:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;v.decode()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setattr(obj,&nbsp;k,&nbsp;v)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;obj<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;deserializer<br /><br /></span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;obj_list_serializer(obj):<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;msgpack.dumps(list(vars(obj).values()))<br /><br /></span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;obj_list_deserializer(T):<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;deserializer(buf):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;obj&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;T()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;k,&nbsp;v&nbsp;</span><span style="color: #0000FF; ">in</span><span style="color: #000000; ">&nbsp;zip(vars(obj).keys(),&nbsp;msgpack.unpackb(buf)):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;type(v)</span><span style="color: #000000; ">==</span><span style="color: #000000; ">bytes:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;v.decode()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setattr(obj,&nbsp;k,&nbsp;v)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;obj<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;deserializer<br /><br /><br /></span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800080; ">__name__</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800000; ">'</span><span style="color: #800000; ">__main__</span><span style="color: #800000; ">'</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">from</span><span style="color: #000000; ">&nbsp;dataclasses&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;dataclass<br />&nbsp;&nbsp;&nbsp;&nbsp;@dataclass<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Stu:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id&nbsp;:&nbsp;int&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;0<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name:&nbsp;str&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800000; ">""</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stuno:&nbsp;str&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800000; ">""</span><span style="color: #000000; "><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;stu1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Stu(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #800000; ">张三</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #800000; ">190003160</span><span style="color: #800000; ">"</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;stu2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Stu(</span><span style="color: #000000; ">2</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #800000; ">李四</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #800000; ">190003161</span><span style="color: #800000; ">"</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;buf1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;obj_dict_serializer(stu1)<br />&nbsp;&nbsp;&nbsp;&nbsp;stu1_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;obj_dict_deserializer(Stu)(buf1)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(stu1,&nbsp;stu1_)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(stu1&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;stu1_)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;buf2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;obj_dict_serializer(stu2)<br />&nbsp;&nbsp;&nbsp;&nbsp;stu2_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;obj_dict_deserializer(Stu)(buf2)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(stu2,&nbsp;stu2_)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(stu2&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;stu2_)<br /><br /><br /></span></div></div><div>配合在C++上使用msgpack.hpp 像class、struct中添加 MSGPACK_DEFINE 或 MSGPACK_DEFINE_MAP，可以实现python和C++之间的数据互传后的编解码</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/91959.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2019-11-20 00:00 <a href="http://www.cnitblog.com/luckydmz/archive/2019/11/20/91959.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python虚拟环境virtualenv</title><link>http://www.cnitblog.com/luckydmz/archive/2019/11/17/91957.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Sun, 17 Nov 2019 06:07:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2019/11/17/91957.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/91957.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2019/11/17/91957.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/91957.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/91957.html</trackback:ping><description><![CDATA[<div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">安装</div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000; ">pip3&nbsp;install&nbsp;virtualenv<br />
pip3&nbsp;install&nbsp;virtualenvwrapper</span></div>
<br />
<div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">修改用户家目录下的配置文件.bashrc，添加如下内容：</div>
<div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000; ">export&nbsp;WORKON_HOME</span><span style="color: #000000; ">=</span><span style="color: #000000; ">$HOME</span><span style="color: #000000; ">/</span><span style="color: #000000; ">.virtualenvs
export&nbsp;VIRTUALENVWRAPPER_PYTHON</span><span style="color: #000000; ">=/</span><span style="color: #000000; ">usr</span><span style="color: #000000; ">/</span><span style="color: #000000; ">bin</span><span style="color: #000000; ">/</span><span style="color: #000000; ">python3
source&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">usr</span><span style="color: #000000; ">/</span><span style="color: #000000; ">local</span><span style="color: #000000; ">/</span><span style="color: #000000; ">bin</span><span style="color: #000000; ">/</span><span style="color: #000000; ">virtualenvwrapper.sh</span>
</div></div>
<br />
<div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">执行.bashrc，让修改立即生效</div>
<div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">source ~/.bashrc</div>
<br />
<div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">创建虚拟环境</div>
<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">mkvirtualenv &lt;环境名&gt;</div>
<br />
<div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">进入虚拟环境</div>
<div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">workon &lt;环境名&gt;</div>
<br />
<div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">从虚拟环境中退出</div>
<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">deactivate</div>
<br />
<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">删除虚拟环境</div>
<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">rmvirtualenv &lt;环境名&gt;</div>
<br />
<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">导出当前环境已安装的包</div>
<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">pip freeze &gt; requirements.txt</div>
<br />
<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">安装包列表</div>
<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">pip install [-i https://指定安装源] -r requirements.txt</div>
<br />
<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">国内可选安装源地址：</div>
<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">阿里云&nbsp;<a href="http://mirrors.aliyun.com/pypi/simple/"><span style="color: #003884; text-decoration: underline;">http://mirrors.aliyun.com/pypi/simple/</span></a></div>
<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">清华大学&nbsp;<a href="https://pypi.tuna.tsinghua.edu.cn/simple/"><span style="color: #003884; text-decoration: underline;">https://pypi.tuna.tsinghua.edu.cn/simple/</span></a></div>
<br />
<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">永久更换安装源</div>
<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">编辑 ~/.pip/pip.conf</div>
<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008000; ">#</span><span style="color: #008000; ">#&nbsp;Note,&nbsp;this&nbsp;file&nbsp;is&nbsp;written&nbsp;by&nbsp;cloud-init&nbsp;on&nbsp;first&nbsp;boot&nbsp;of&nbsp;an&nbsp;instance</span><span style="color: #008000; "><br />
#</span><span style="color: #008000; ">#&nbsp;modifications&nbsp;made&nbsp;here&nbsp;will&nbsp;not&nbsp;survive&nbsp;a&nbsp;re-bundle.</span><span style="color: #008000; "><br />
#</span><span style="color: #008000; ">##</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">[</span><span style="color: #0000FF; ">global</span><span style="color: #000000; ">]<br />
index</span><span style="color: #000000; ">-</span><span style="color: #000000; ">url</span><span style="color: #000000; ">=</span><span style="color: #000000; ">http:</span><span style="color: #000000; ">//</span><span style="color: #000000; ">mirrors.cloud.aliyuncs.com</span><span style="color: #000000; ">/</span><span style="color: #000000; ">pypi</span><span style="color: #000000; ">/</span><span style="color: #000000; ">simple</span><span style="color: #000000; ">/</span><span style="color: #000000; "><br />
<br />
[install]<br />
trusted</span><span style="color: #000000; ">-</span><span style="color: #000000; ">host</span><span style="color: #000000; ">=</span><span style="color: #000000; ">mirrors.cloud.aliyuncs.com</span></div><img src ="http://www.cnitblog.com/luckydmz/aggbug/91957.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2019-11-17 14:07 <a href="http://www.cnitblog.com/luckydmz/archive/2019/11/17/91957.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python中设置Thread超时(Timeout)结束或主动杀死(Kill)</title><link>http://www.cnitblog.com/luckydmz/archive/2019/11/16/91953.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Sat, 16 Nov 2019 13:51:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2019/11/16/91953.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/91953.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2019/11/16/91953.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/91953.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/91953.html</trackback:ping><description><![CDATA[<div><span style="font-size: 12pt;">先上正确的代码</span></div><div><span style="font-size: 12pt;">参考 https://blog.csdn.net/vinsuan1993/article/details/78158589/<br /></span></div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;threading<br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;time<br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;inspect<br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;ctypes<br /><br /></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;KillableThread(threading.Thread):<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800080; ">__init__</span><span style="color: #000000; ">(self,&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">args,&nbsp;</span><span style="color: #000000; ">**</span><span style="color: #000000; ">kw):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(KillableThread,&nbsp;self).</span><span style="color: #800080; ">__init__</span><span style="color: #000000; ">(</span><span style="color: #000000; ">*</span><span style="color: #000000; ">args,&nbsp;</span><span style="color: #000000; ">**</span><span style="color: #000000; ">kw)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;_async_raise(tid,&nbsp;exctype):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800000; ">"""</span><span style="color: #800000; ">raises&nbsp;the&nbsp;exception,&nbsp;performs&nbsp;cleanup&nbsp;if&nbsp;needed</span><span style="color: #800000; ">"""</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tid&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;ctypes.c_long(tid)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">not</span><span style="color: #000000; ">&nbsp;inspect.isclass(exctype):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exctype&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;type(exctype)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,&nbsp;ctypes.py_object(exctype))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;res&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;0:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">raise</span><span style="color: #000000; ">&nbsp;ValueError(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">invalid&nbsp;thread&nbsp;id</span><span style="color: #800000; ">"</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">elif</span><span style="color: #000000; ">&nbsp;res&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;"""if&nbsp;it&nbsp;returns&nbsp;a&nbsp;number&nbsp;greater&nbsp;than&nbsp;one,&nbsp;you're&nbsp;in&nbsp;trouble,</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;and&nbsp;you&nbsp;should&nbsp;call&nbsp;it&nbsp;again&nbsp;with&nbsp;exc=NULL&nbsp;to&nbsp;revert&nbsp;the&nbsp;effect"""</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,&nbsp;None)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">raise</span><span style="color: #000000; ">&nbsp;SystemError(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">PyThreadState_SetAsyncExc&nbsp;failed</span><span style="color: #800000; ">"</span><span style="color: #000000; ">)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;kill(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KillableThread._async_raise(self.ident,&nbsp;SystemExit)<br /><br /><br /></span><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;循环输出s，t次，每0.6秒一次</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;say(s,t):<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #0000FF; ">in</span><span style="color: #000000; ">&nbsp;range(t):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(s)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(</span><span style="color: #000000; ">0.6</span><span style="color: #000000; ">)<br /><br /></span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800080; ">__name__</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #800000; ">__main__</span><span style="color: #800000; ">"</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;&nbsp;&nbsp;thread1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;KillableThread(target</span><span style="color: #000000; ">=</span><span style="color: #000000; ">say,&nbsp;args</span><span style="color: #000000; ">=</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">Say&nbsp;3&nbsp;times</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">3</span><span style="color: #000000; ">))<br />&nbsp;&nbsp;&nbsp;&nbsp;thread1.start()&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;thread1.join()<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">Alive?&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;thread1.is_alive())<br />&nbsp;&nbsp;&nbsp;&nbsp;thread2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;KillableThread(target</span><span style="color: #000000; ">=</span><span style="color: #000000; ">say,&nbsp;args</span><span style="color: #000000; ">=</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">Say&nbsp;999&nbsp;times</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">999</span><span style="color: #000000; ">))<br />&nbsp;&nbsp;&nbsp;&nbsp;thread2.start()<br />&nbsp;&nbsp;&nbsp;&nbsp;thread2.join(</span><span style="color: #000000; ">2</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">Alive?&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;thread2.is_alive())<br />&nbsp;&nbsp;&nbsp;&nbsp;thread2.kill()<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">Still&nbsp;alive?&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;thread2.is_alive())<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;查看线程数量</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">&nbsp;True:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread_num&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;len(threading.enumerate())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">线程数量是%d</span><span style="color: #800000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">%</span><span style="color: #000000; ">&nbsp;thread_num)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;thread_num&nbsp;</span><span style="color: #000000; ">&lt;=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">break</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">Still&nbsp;alive?&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;thread2.is_alive())</span></div><span style="font-size: 12pt;"></span></div><div><span style="font-size: 12pt;">输出为</span></div><div><span style="font-size: 12pt;">Say 3 times<br />Say 3 times<br />Say 3 times<br />Alive?&nbsp; False<br />Say 999 times<br />Say 999 times<br />Say 999 times<br />Say 999 times<br />Alive?&nbsp; True<br />Still alive?&nbsp; True<br />线程数量是2<br />线程数量是1<br />Still alive?&nbsp; False<br /></span></div><div><span style="font-size: 12pt;"><br /></span></div><div><span style="font-size: 12pt; color: red;">------ 分割线以下分析是错的 ------</span><span style="font-size: 12pt;"><br /></span></div><div><br /><span style="font-size: 12pt;"><span style="font-size: 12pt; color: red;">后面的代码是错误的，错误在于setDaemon是让被设置的线程随主线程一起结束，而不是父线程，我不清楚这样有什么意义。之所以没有发现下面代码是错的，是因为正好主线程后面就结束了，如果让主线程继续空转就会看到999那个线程还在输出</span></span></div><div><span style="font-size: 12pt;">Python中的threading.Thread并没有提供kill方法杀死尚未结束的线程，但是提供了<strong>setDaemon</strong>方法设置守护线程，守护线程会在父线程结束时自动结束。</span></div><div><span style="font-size: 12pt;">注意父线程是调用线程start()的线程，而不是创建threading.Thread对象的线程，下面的代码演示了通过setDaemon方法让线程超时自动结束。</span></div><div><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; "><br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;threading<br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;time<br />
<br />
</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;start_thread_with_timeout(target,&nbsp;secs:int,&nbsp;args</span><span style="color: #000000; ">=</span><span style="color: #000000; ">None):<br />
&nbsp;&nbsp;&nbsp;&nbsp;th&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;threading.Thread(target</span><span style="color: #000000; ">=</span><span style="color: #000000; ">target,&nbsp;args</span><span style="color: #000000; ">=</span><span style="color: #000000; ">args)<br />
&nbsp;&nbsp;&nbsp;&nbsp;timeout&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;True<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;daemon_thread():<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800000; ">'''</span><span style="color: #800000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;对于嵌套定义的函数，当Python发现读取一个不存在的变量时，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;会向外层去找，而当给一个变量赋值时，若函数内不存在此变量，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;优先创建而不向外找，所以此处timeout必须声明为nonlocal，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;而对th的声明是可选的<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800000; ">'''</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;声明外部变量</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nonlocal&nbsp;timeout,&nbsp;th<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;th.setDaemon(True)&nbsp;</span><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;设置为守护线程，会在它的父线程结束时自动结束</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;th.start()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;th.join(secs)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeout&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;th.is_alive()<br />
&nbsp;&nbsp;&nbsp;&nbsp;guard&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;threading.Thread(target</span><span style="color: #000000; ">=</span><span style="color: #000000; ">daemon_thread)<br />
&nbsp;&nbsp;&nbsp;&nbsp;guard.start()<br />
&nbsp;&nbsp;&nbsp;&nbsp;guard.join()<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;timeout<br />
<br />
</span><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;循环输出s，t次，每0.6秒一次</span><span style="color: #008000; "><br />
</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;say(s,t):<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #0000FF; ">in</span><span style="color: #000000; ">&nbsp;range(t):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(s)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(</span><span style="color: #000000; ">0.6</span><span style="color: #000000; ">)<br />
<br />
</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800080; ">__name__</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #800000; ">__main__</span><span style="color: #800000; ">"</span><span style="color: #000000; ">:<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;输出字符串3次，每次间隔0.6s，2s后超时，所以此处应该不会超时结束</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;timeout&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;start_thread_with_timeout(target</span><span style="color: #000000; ">=</span><span style="color: #000000; ">say,&nbsp;args</span><span style="color: #000000; ">=</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">Say&nbsp;3&nbsp;times</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">3</span><span style="color: #000000; ">),&nbsp;secs</span><span style="color: #000000; ">=</span><span style="color: #000000; ">2</span><span style="color: #000000; ">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">Timeout?&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;timeout)<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;输出字符串999次，每次间隔0.6s，2s后超时，所以此处应该不会超时结束</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;timeout&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;start_thread_with_timeout(target</span><span style="color: #000000; ">=</span><span style="color: #000000; ">say,&nbsp;args</span><span style="color: #000000; ">=</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">Say&nbsp;999&nbsp;times</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">999</span><span style="color: #000000; ">),&nbsp;secs</span><span style="color: #000000; ">=</span><span style="color: #000000; ">2</span><span style="color: #000000; ">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">Timeout?&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;timeout)</span></div>
</div>
<div>程序输出为：</div>
<div>Say 3 times<br />
Say 3 times<br />
Say 3 times<br />
Timeout?&nbsp; False<br />
Say 999 times<br />
Say 999 times<br />
Say 999 times<br />
Say 999 times<br />
Timeout?&nbsp; True</div><div><span style="font-size: 12pt;">清楚原理后也可以用来实现kill的功能，例如可以让哨兵线程每隔一个时间片查询一次需要kill的flag，不过这样没有办法实时杀死线程，时间片设太大就延迟杀死，设太小会频繁占用CPU，解决方法可以通过信号量(</span><strong style="font-size: 12pt;">semaphore</strong><span style="font-size: 12pt;">)或者条件变量(</span><strong style="font-size: 12pt;">condition</strong><span style="font-size: 12pt;">)让哨兵线程陷入睡眠，外部调用kill唤醒哨兵线程直接结束就可以了。</span><br style="font-size: 12pt;" /><span style="font-size: 12pt;">（哨兵线程：守卫线程的父线程，可以看做是真正要执行的线程的哨兵，所以我称之为哨兵线程）</span></div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;threading<br /></span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;time<br /><br /></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;KillableThread:<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800080; ">__init__</span><span style="color: #000000; ">(self,&nbsp;target,&nbsp;args</span><span style="color: #000000; ">=</span><span style="color: #000000; ">None):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.th&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;threading.Thread(target</span><span style="color: #000000; ">=</span><span style="color: #000000; ">target,&nbsp;args</span><span style="color: #000000; ">=</span><span style="color: #000000; ">args)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.kill_sema&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;threading.Semaphore(0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.start_sema&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;threading.Semaphore(0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;daemon_thread(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.th.setDaemon(True)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.th.start()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.start_sema.release()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.kill_sema.acquire()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.guard&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;threading.Thread(target</span><span style="color: #000000; ">=</span><span style="color: #000000; ">daemon_thread,&nbsp;args</span><span style="color: #000000; ">=</span><span style="color: #000000; ">(self,))<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;start(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.guard.start()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.start_sema.acquire()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;join(self,&nbsp;secs</span><span style="color: #000000; ">=</span><span style="color: #000000; ">None):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.th.join(secs)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">not</span><span style="color: #000000; ">&nbsp;self.th.is_alive():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.kill_sema.release()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;is_alive(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;self.th.is_alive()&nbsp;</span><span style="color: #0000FF; ">and</span><span style="color: #000000; ">&nbsp;self.guard.is_alive()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;kill(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.kill_sema.release()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">&nbsp;self.guard.is_alive():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">pass</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;<br /><br /><br /></span><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;循环输出s，t次，每0.6秒一次</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;say(s,t):<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #0000FF; ">in</span><span style="color: #000000; ">&nbsp;range(t):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(s)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(</span><span style="color: #000000; ">0.6</span><span style="color: #000000; ">)<br /><br /></span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800080; ">__name__</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #800000; ">__main__</span><span style="color: #800000; ">"</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;&nbsp;&nbsp;thread1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;KillableThread(target</span><span style="color: #000000; ">=</span><span style="color: #000000; ">say,&nbsp;args</span><span style="color: #000000; ">=</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">Say&nbsp;3&nbsp;times</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">3</span><span style="color: #000000; ">))<br />&nbsp;&nbsp;&nbsp;&nbsp;thread1.start()<br />&nbsp;&nbsp;&nbsp;&nbsp;thread1.join()<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">Alive?&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;thread1.is_alive())<br />&nbsp;&nbsp;&nbsp;&nbsp;thread2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;KillableThread(target</span><span style="color: #000000; ">=</span><span style="color: #000000; ">say,&nbsp;args</span><span style="color: #000000; ">=</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">Say&nbsp;999&nbsp;times</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">999</span><span style="color: #000000; ">))<br />&nbsp;&nbsp;&nbsp;&nbsp;thread2.start()<br />&nbsp;&nbsp;&nbsp;&nbsp;thread2.join(</span><span style="color: #000000; ">2</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">Alive?&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;thread2.is_alive())<br />&nbsp;&nbsp;&nbsp;&nbsp;thread2.kill()<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">Still&nbsp;alive?&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;thread2.is_alive())</span></div><span style="font-size: 12pt;"></span></div><img src ="http://www.cnitblog.com/luckydmz/aggbug/91953.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2019-11-16 21:51 <a href="http://www.cnitblog.com/luckydmz/archive/2019/11/16/91953.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>