最近在研究热力图,发现了一篇可能有用的Python
模拟疫情扩散的文章,可以部分模拟热力图,整篇文章原文内容如下:
分类: Python
Python(KK 英语发音:/ˈpaɪθən/), 是一种面向对象、直译式计算机程序设计语言,由Guido van Rossum于1989年底发明,第一个公开发行版发行于1991年。Python语法简洁而清晰,具有丰富和强大的类库。它常被昵称为胶水语言,它能够很轻松的把用其他语言制作的各种模块(尤其是C/C++)轻松地联结在一起。
ubuntu 14.04.5下安装多版本Python(2.7.6/3.4.3/3.6.4)
系统环境:ubuntu14.04.5 LTS
,系统默认的python
版本为2.7.4/3.4.3
。
但是实际工作中,某些通过pip
安装的开发包需要不低于某个版本的python
才能正常工作,比如ansible-2.4.2.0
,明确只支持python-3.5
以上的版本。在低版本的python
上,无法正常运行。
而如果我们贸然更新系统python
版本的话,会导致系统异常。因此我们借助pyenv
实现基于用户的python
版本定制。
安装pyenv
:
1 2 3 4 5 6 7 8 9 |
$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv $ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc $ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc $ echo 'eval "$(pyenv init -)"' >> ~/.bashrc $ exec $SHELL -l |
查看可以安装的python
版本:
1 |
$ pyenv install --list |
这里以安装python-3.6.4
为例,首先安装依赖:
1 |
$ sudo apt-get install -y make build-essential |
安装python
:
1 2 3 4 |
# 要求开启Python动态库的支持(默认是全部静态编译),否则在安装某些插件的时候会出现无法正常链接的情况,比如 mod_wsgi $ export PYTHON_CONFIGURE_OPTS="--enable-shared" $ pyenv install 3.6.4 -vvv |
该命令会从github
上下载python
的源代码,并解压到/tmp
目录下,然后在/tmp
中执行编译工作。若依赖包没有安装,则会出现编译错误,需要在安装依赖包之后重新执行该命令。
安装完成之后,需要使用如下命令对数据库进行更新:
1 |
$ pyenv rehash |
查看当前已经安装的python
版本
1 2 3 |
$ pyenv versions * system (set by /home/xxx/.pyenv/version) 3.6.4 |
其中星号代表是当前系统正在使用的python
版本是系统自带的。
设置全局的python
版本
1 2 3 4 5 |
$ pyenv global 3.6.4 $ pyenv versions system * 3.6.4 (set by /home/xxx/.pyenv/version) |
从上面,我们可以看出来当前的python
版本已经变为了3.6.4
。也可以使用pyenv local
或pyenv shell
临时改变python
的版本。
如果需要还原设定的python
版本为系统自带的版本,则执行如下命令:
1 |
$ pyenv global system |
确认python
版本
1 2 3 4 |
$ python Python 3.6.4 (default, Jan 9 2018, 11:21:57) [GCC 4.8.4] on linux Type "help", "copyright", "credits" or "license" for more information. |
上面的操作会导致在当前用户下,执行python
或者python3
命令的时候都会被定向到python-3.6.4
,如果只想执行python3
命令的时候被定向到python-3.6.4
,则可以直接删除python
这个链接:
1 2 3 |
# 注意,这个链接删除后,可能导致ros indigo的初始化异常,因此,这部分的改动要慎重 $ rm -rf ~/.pyenv/versions/3.6.4/bin/python |
安装pip
:
1 2 3 4 5 6 7 |
$ wget https://bootstrap.pypa.io/get-pip.py $ python3 get-pip.py $ rm -rf get-pip.py $ pip3 install --upgrade pip |
安装完成之后,需要使用如下命令对数据库进行更新:
1 |
$ pyenv rehash |
注意事项:
- 输入
python
即可使用新版的python
- 系统自带的脚本会以
/usr/bin/python
的方式直接调用老版本的python
,因而不会对系统脚本产生影响 - 使用
pip
安装第三方模块时会安装到~/.pyenv/versions/3.6.4
下,不会和系统模块发生冲突 - 使用
pip
安装模块后,可能需要执行pyenv rehash
更新数据库
参考链接
Python中用Ctrl+C终止threading初始化的多线程脚本
在编写Python
脚本的时候,难免会遇到使用多线程操作的情况。
正常情况下,我们都习惯在Shell
中使用Ctrl+C
终止脚本的执行,但是在多线程环境中,我们发现Ctrl+C
并不能有效终止开启了多线程的脚本。
由于Python
提供的threading
模块并没有提供线程的退出接口,导致我们没有办法终止已经正常运行的线程,尤其是线程被阻塞在内核的情况下。
解决这个问题的办法就是在线程初始化之后设置为守护模式(setDaemon
),并且不要调用join
阻塞主线程。这样当主线程退出的时候,其他线程也随之退出了。
下面是我们解决这种问题的一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#!/bin/env python # -*- coding: utf-8 -*- import threading import signal import sys import time global is_exit is_exit = False def doWork(i): print "thread[%d] enter\n"%(i) while not is_exit: time.sleep(0.2) print "thread[%d] terminated\n"%(i) def sig_handler(signum, frame): is_exit = True sys.exit(0) if __name__ == "__main__": signal.signal(signal.SIGINT, sig_handler) signal.signal(signal.SIGTERM, sig_handler) cc = 5 for i in range(cc): t = threading.Thread(target=doWork, args=(i,)) t.setDaemon(True) t.start() raw_input("Waiting For Ctrl+C\n") |
参考链接
Python简单实现WebSocket
实现一个简单的聊天室程序,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
#-*- coding:utf8 -*- import threading import hashlib import socket import base64 global clients clients = {} #通知客户端 def notify(message): for connection in clients.values(): connection.send('%c%c%s' % (0x81, len(message), message)) #客户端处理线程 class websocket_thread(threading.Thread): def __init__(self, connection, username): super(websocket_thread, self).__init__() self.connection = connection self.username = username def run(self): print 'new websocket client joined!' data = self.connection.recv(1024) headers = self.parse_headers(data) token = self.generate_token(headers['Sec-WebSocket-Key']) self.connection.send('\ HTTP/1.1 101 WebSocket Protocol Hybi-10\r\n\ Upgrade: WebSocket\r\n\ Connection: Upgrade\r\n\ Sec-WebSocket-Accept: %s\r\n\r\n' % token) while True: try: data = self.connection.recv(1024) except socket.error, e: print "unexpected error: ", e clients.pop(self.username) break data = self.parse_data(data) if len(data) == 0: continue message = self.username + ": " + data notify(message) def parse_data(self, msg): v = ord(msg[1]) & 0x7f if v == 0x7e: p = 4 elif v == 0x7f: p = 10 else: p = 2 mask = msg[p:p+4] data = msg[p+4:] return ''.join([chr(ord(v) ^ ord(mask[k%4])) for k, v in enumerate(data)]) def parse_headers(self, msg): headers = {} header, data = msg.split('\r\n\r\n', 1) for line in header.split('\r\n')[1:]: key, value = line.split(': ', 1) headers[key] = value headers['data'] = data return headers def generate_token(self, msg): key = msg + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' ser_key = hashlib.sha1(key).digest() return base64.b64encode(ser_key) #服务端 class websocket_server(threading.Thread): def __init__(self, port): super(websocket_server, self).__init__() self.port = port def run(self): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(('127.0.0.1', self.port)) sock.listen(5) print 'websocket server started!' while True: connection, address = sock.accept() try: username = "ID" + str(address[1]) thread = websocket_thread(connection, username) thread.start() clients[username] = connection except socket.timeout: print 'websocket connection timeout!' if __name__ == '__main__': server = websocket_server(9000) server.start() |
测试页面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
<!-- @http://www.cnblogs.com/zhuweisky/p/3930780.html --> <!DOCTYPE html> </html> <head> <meta charset="utf-8"> </head> <body> <h3>WebSocketTest</h3> <div id="login"> <div> <input id="serverIP" type="text" placeholder="服务器IP" value="127.0.0.1" autofocus="autofocus" /> <input id="serverPort" type="text" placeholder="服务器端口" value="9000" /> <input id="btnConnect" type="button" value="连接" onclick="connect()" /> </div> <div> <input id="sendText" type="text" placeholder="发送文本" value="I'm WebSocket Client!" /> <input id="btnSend" type="button" value="发送" onclick="send()" /> </div> <div> <div> 来自服务端的消息 </div> <textarea id="txtContent" cols="50" rows="10" readonly="readonly"></textarea> </div> </div> </body> <script> var socket; function connect() { var host = "ws://" + $("serverIP").value + ":" + $("serverPort").value + "/" socket = new WebSocket(host); try { socket.onopen = function (msg) { $("btnConnect").disabled = true; alert("连接成功!"); }; socket.onmessage = function (msg) { if (typeof msg.data == "string") { displayContent(msg.data); } else { alert("非文本消息"); } }; socket.onclose = function (msg) { alert("socket closed!") }; } catch (ex) { log(ex); } } function send() { var msg = $("sendText").value socket.send(msg); } window.onbeforeunload = function () { try { socket.close(); socket = null; } catch (ex) { } }; function $(id) { return document.getElementById(id); } Date.prototype.Format = function (fmt) { //author: meizz var o = { "M+": this.getMonth() + 1, //月份 "d+": this.getDate(), //日 "h+": this.getHours(), //小时 "m+": this.getMinutes(), //分 "s+": this.getSeconds(), //秒 "q+": Math.floor((this.getMonth() + 3) / 3), //季度 "S": this.getMilliseconds() //毫秒 }; if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); for (var k in o) if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); return fmt; } function displayContent(msg) { $("txtContent").value += "\r\n" +new Date().Format("yyyy/MM/dd hh:mm:ss")+ ": " + msg; } function onkey(event) { if (event.keyCode == 13) { send(); } } </script> </html> |
参考链接
Ubuntu 16.04下用Python显示YUV格式的图片
YUV420p to RGB & view
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
from PIL import Image import sys from struct import * import array if len(sys.argv) != 4: print "***** Usage syntax Error!!!! *****\n" print "Usage:" print "python <script> <.yuv file yuv420p> <width>> <height> " sys.exit(1) # exit else: pass image_name = sys.argv[1] width = int(sys.argv[2]) height = int(sys.argv[3]) y = array.array('B') u = array.array('B') v = array.array('B') f_y = open(image_name, "rb") f_uv = open(image_name, "rb") f_uv.seek(width*height, 1) image_out = Image.new("RGB", (width, height)) pix = image_out.load() print "width=", width, "height=", height for i in range(0, height/2): for j in range(0, width/2): u.append(ord(f_uv.read(1))); for i in range(0, height/2): for j in range(0, width/2): v.append(ord(f_uv.read(1))); for i in range(0,height): for j in range(0, width): y.append(ord(f_y.read(1))); #print "i=", i, "j=", j , (i*width), ((i*width) +j) #pix[j, i] = y[(i*width) +j], y[(i*width) +j], y[(i*width) +j] Y_val = y[(i*width)+j] U_val = u[((i/2)*(width/2))+(j/2)] V_val = v[((i/2)*(width/2))+(j/2)] B = 1.164 * (Y_val-16) + 2.018 * (U_val - 128) G = 1.164 * (Y_val-16) - 0.813 * (V_val - 128) - 0.391 * (U_val - 128) R = 1.164 * (Y_val-16) + 1.596*(V_val - 128) pix[j, i] = int(R), int(G), int(B) ###################################################### # B = 1.164(Y - 16) + 2.018(U - 128) # G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) # R = 1.164(Y - 16) + 1.596(V - 128) ###################################################### #image_out.save("out.bmp") image_out.show() |
UYVY/YUV422 to RGB and view:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
from PIL import Image import sys from struct import * import array if len(sys.argv) != 4: print "***** Usage syntax Error!!!! *****\n" print "Usage:" print "python <script> <.yuv file uyvy422> <width>> <height> " sys.exit(1) # exit else: pass image_name = sys.argv[1] width = int(sys.argv[2]) height = int(sys.argv[3]) y = array.array('B') u = array.array('B') v = array.array('B') f_uyvy = open(image_name, "rb") f_uv = open(image_name, "rb") f_uv.seek(width*height, 1) image_out = Image.new("RGB", (width, height)) pix = image_out.load() print "width=", width, "height=", height for i in range(0,height): for j in range(0, width/2): u = ord(f_uyvy.read(1)); y1 = ord(f_uyvy.read(1)); v = ord(f_uyvy.read(1)); y2 = ord(f_uyvy.read(1)); B = 1.164 * (y1-16) + 2.018 * (u - 128) G = 1.164 * (y1-16) - 0.813 * (v - 128) - 0.391 * (u - 128) R = 1.164 * (y1-16) + 1.596*(v - 128) pix[j*2, i] = int(R), int(G), int(B) B = 1.164 * (y2-16) + 2.018 * (u - 128) G = 1.164 * (y2-16) - 0.813 * (v - 128) - 0.391 * (u - 128) R = 1.164 * (y2-16) + 1.596*(v - 128) pix[j*2+1, i] = int(R), int(G), int(B) ###################################################### # B = 1.164(Y - 16) + 2.018(U - 128) # G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) # R = 1.164(Y - 16) + 1.596(V - 128) ###################################################### #image_out.save("out.bmp") image_out.show() |
原始链接
Python matplotlib.pyplot.draw()在不同版本中的差别导致界面绘制异常问题
在Ubuntu
系统上进行如下配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ sudo apt-get update $ sudo apt-get upgrade $ sudo apt-get install python-dev $ sudo apt-get install python-pip $ sudo pip install --upgrade pip $ sudo pip install --upgrade urllib3 $ sudo pip install numpy $ sudo pip install matplotlib |
之后执行如下测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import sys import numpy as np import matplotlib.pyplot as plt plt.ion() (fig, axis) = plt.subplots() bar_plot = axis.barh(0, 8,linewidth = 0) bar_plot.color= '#ffff00' for i in range(20): axis.set_xlim(xmax = max(i + 1, 10)) plt.draw() if sys.version_info < (3, 0): raw_input("Press Enter to continue...") else: input("Press Enter to continue...") |
上面的测试代码在Ubuntu 14.04.5
版本上是可以正常执行的,对应的matplotlib
的版本是matplotlib 1.3.1
,但是放到Ubuntu 16.04.2
系统上则是无法正常显示的,对应的matplotlib
的版本是matplotlib 1.5.1
。
造成这个问题的原因在于matplotlib.pyplot.draw()
,这个函数行为的改变,早期这个函数是同步更新界面的,后来的版本却变成了空闲异步更新界面,只有当matplotlib.pyplot.pause(interval)
被调用的时候才会刷新界面。
所以只需要上面的代码修改成如下即可在不同版本之间兼容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import sys import numpy as np import matplotlib.pyplot as plt plt.ion() (fig, axis) = plt.subplots() bar_plot = axis.barh(0, 8,linewidth = 0) bar_plot.color= '#ffff00' for i in range(20): axis.set_xlim(xmax = max(i + 1, 10)) plt.draw() plt.pause(0.00001) if sys.version_info < (3, 0): raw_input("Press Enter to continue...") else: input("Press Enter to continue...") |
注意,我们在matplotlib.pyplot.draw()
调用后面增加了matplotlib.pyplot.pause(interval)
的调用。
貌似调用fig.canvas.flush_events()
更合适?
查看matplotlib
的版本使用如下代码:
1 2 |
import matplotlib as mpl print mpl.__version__ |
参考链接
Ubuntu 14.04系统上Python使用"subprocess.Popen"执行"source"命令报告错误“/bin/sh: source: not found”
使用如下的例子中的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import subprocess def execShellCommand(cmd): print cmd p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) while True: buff = p.stdout.readline() if buff == '' and p.poll() != None: break print buff p.wait() def main(): execShellCommand("source ~/.profile") if __name__ == "__main__": main() |
运行的时候报告错误
1 2 |
source ~/.profile /bin/sh: 1: source: not found |
这个错误发生的原因是subprocess.Popen
执行Shell
命令的时候默认调用/bin/sh
,而source
命令/bin/bash
才支持的,因此导致错误发生,修改后的脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import subprocess def execShellCommand(cmd): print cmd p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,executable="/bin/bash") while True: buff = p.stdout.readline() if buff == '' and p.poll() != None: break print buff p.wait() def main(): execShellCommand("source ~/.profile") if __name__ == "__main__": main() |
注意添加的executable="/bin/bash"
,指明了执行脚本的执行程序是/bin/bash
。
参考链接
ubuntu 16.04执行letsencrypt的时候报告错误“ImportError: No module named datetime”
网站一直使用letsencrypt
提供的HTTPS
证书,这个证书的问题在于每隔三个月就必须更新一次,本次更新证书的时候,提示如下错误:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
Error: couldn't get currently installed version for /root/.local/share/letsencrypt/bin/letsencrypt: Traceback (most recent call last): File "/root/.local/share/letsencrypt/bin/letsencrypt", line 7, in <module> from certbot.main import main File "/root/.local/share/letsencrypt/local/lib/python2.7/site-packages/certbot/main.py", line 9, in <module> from acme import jose File "/root/.local/share/letsencrypt/local/lib/python2.7/site-packages/acme/jose/__init__.py", line 37, in <module> from acme.jose.interfaces import JSONDeSerializable File "/root/.local/share/letsencrypt/local/lib/python2.7/site-packages/acme/jose/interfaces.py", line 9, in <module> from acme.jose import util File "/root/.local/share/letsencrypt/local/lib/python2.7/site-packages/acme/jose/util.py", line 4, in <module> from cryptography.hazmat.primitives.asymmetric import rsa File "/root/.local/share/letsencrypt/local/lib/python2.7/site- packages/cryptography/hazmat/primitives/asymmetric/rsa.py", line 14, in <module> from cryptography.hazmat.backends.interfaces import RSABackend File "/root/.local/share/letsencrypt/local/lib/python2.7/site- packages/cryptography/hazmat/backends/__init__.py", line 7, in <module> import pkg_resources File "/root/.local/share/letsencrypt/local/lib/python2.7/site-packages/pkg_resources/__init__.py", line 36, in <module> import plistlib File "/usr/lib/python2.7/plistlib.py", line 62, in <module> import datetime ImportError: No module named datetime |
错误发生的原因在于letsencrypt
自己构建了一个Python
的虚拟环境来隔离,但是早期建立的虚拟环境中是缺少部分软件包的,而自身的BUG
导致也没有重新更新虚拟环境,导致出现异常。
解决方法就是删除letsencrypt
自己构建的Python
的虚拟环境,然后继续执行脚本让他重建即可。
1 |
$ rm -rf ~/.local/share/letsencrypt |
参考链接
Python 2.7中PIL.Image转换为OpenCV支持的Image格式
1 2 |
pil_image = PIL.Image.open('image.jpg') cv_image = cv2.cvtColor(numpy.asarray(pil_image), cv2.COLOR_RGB2BGR) |
参考链接
TypeError: slice indices must be integers or None or have an __index__ method
执行如下Python
脚本时
1 2 3 4 5 6 7 8 9 10 11 |
import numpy as np dy = [0,1,2] edy = [0,1,2] dy[0:2] = np.fix(dy[0:2]) edy[0:2] = np.fix(edy[0:2]) box = [[1,2,3,4],[3,4,5,6]] box2 = box[dy[0]:edy[2]] |
会遇到错误信息
1 2 3 4 |
Traceback (most recent call last): File "test.py", line 11, in <module> box2 = box[dy[0]:edy[2]] TypeError: slice indices must be integers or None or have an __index__ method |
这个提示非常具有迷惑性,会让人不知所措。
其实非常简单
1 |
dy[0:2] = np.fix(dy[0:2]) |
这行导致整个数组变成了浮点数格式的数组,可以试着打印出结果,就会发现整个里面的数字完全变成了浮点数。
而浮点数是不可以用来作为数组的下标的。
修改成如下方式即可
1 2 3 4 5 6 7 8 9 10 11 |
import numpy as np dy = [0,1,2] edy = [0,1,2] dy[0:2] = np.fix(dy[0:2]) edy[0:2] = np.fix(edy[0:2]) box = [[1,2,3,4],[3,4,5,6]] box2 = box[int(dy[0]):int(edy[2])] |
请注意最后的
1 |
int() |
函数,强制转换浮点数为整数。