python中的for..else语法

学生ppt提到了一个示例代码(现在回过头来看,这个语句对初学者而言,难度有点高了),里面用了一个for..else语法。这个代码让我很诧异。

num=[]
for i in range(2,100):
    for j in range(2,i):
        if i%j==0: break
    else:
        num.append(i)
print(num)

这个示例代码是求100以内的质数。算法本身很简单,但for..else语言在别的编程语言里很少有用到,我算是第一次见到这种逻辑控制,开始我还误以为else是匹配到if中。

在网上搜索后,这个网站讲的很明白:

https://foofish.net/for-else.html

简言之:for..else语句,只要for语句中没有执行break语句,则else中代码必然要执行。

巧用pandas进行数据处理

某一原始数据,在数据获取过程中少进行了一个strip处理,导致数据表现为:

,”
2015-01-01 02:56
“,0
,”2018-
01-01 02:56
“,0

其正常应该为一个时间型数据,如:

2015-01-01 02:56
2018-01-01 02:56

而此数据就无法导入数据库进行进一步的处理,因此需要先将其数据进行修正。首先想的是用sed、vi进行处理,但其都是在行上进行处理,而pandas可以在列上进行处理,使其处理不会影响到其他列,因此就使用pandas进行处理:

import pandas as pd
df=pd.read_csv('/path/to/do.csv')
df['ts_created']=df['ts_created'].str.replace('\n\s+','')
df.to_csv('/path/to/out.csv')

遭遇Out of memory: Kill process or sacrifice child

在调试一个爬虫程序时,发现一个非常奇怪的问题,程序总是在运行一段时候会被系统给Kill掉,在syslog里看到:

Nov 9 11:52:20 iZrj9iqn00z9x3jgz1v2t5Z kernel: [5542452.233851] Out of memory: Kill process 10526 (python3) score 738 or sacrifice child

服务器是1台2G内存的云服务器,内存不够?那就暂时使用虚拟内存扩充上来:
swapoff -a
dd if=/dev/zero of=swapfile bs=1024 count=4000000
mkswap swapfile
swapon swapfile

这样就临时加了4G虚拟内存上来,保证程序在峰值运行时不被kill。

参考:https://plumbr.io/blog/memory-leaks/out-of-memory-kill-process-or-sacrifice-child

Python:在循环中移除循环体要素

改造之前一个数据处理代码,需要在循环中根据判断条件来决定是否移除当前的循环体对象。

简单示例代码:

>>> lst = [1, 2, 3, 4, 5, 6, 7, 8]
>>> for x in lst:
        if x < 6: lst.remove(x) 
>>> lst
[2, 4, 6, 7, 8]

这个示例中返回结果有错误,即本意是要移除x<6的对象,但最终并没有完全移除,造成了隔一个移除的结果。造成错误结果的主要原因是循环体在循环过程中并不知道循环体发生了变化,导致循环体在定位到下一个循环体对象时发生了位移。其解决方案也比较简单:

1、拷贝一个循环体,使用拷贝后的循环体进行循环,而修改则在原来的循环体,这样就互不影响。

2、对循环体使用reversed()函数,即:

>>> lst = [1, 2, 3, 4, 5, 6, 7, 8]
>>> for x in reversed(lst):
        if x < 6: lst.remove(x) 
>>> lst
[6, 7, 8]

 

参考:

https://sopython.com/canon/95/removing-items-from-a-list-while-iterating-over-the-list/

 

使用wordcloud生成中文词云的汉字编码问题

用python对市长信箱的回复选登进行分析,需要作词云图,选择wordcloud包来实现。

网上很多都介绍了生成中文词云需要指定中文字体的路径,但我在使用中还遇到了utf8编码与unicode编码的转换问题。即utf8编码的字符串需要先转换为unicode编码,然后再送入wordcloud的fit_words方法才能正确显示中文词云。

示例代码如下:

rec=records
for i in range(0,len(records)):
	rec[i]=(unicode(records[i][0]),records[i][1])

tags=dict(rec)
wordcloud=WordCloud(font_path="/Users/wangliangxu/Desktop/SimSun.ttf",width=1200,height=600,max_words=400).fit_words(tags)

Window环境下qgis standalone程序开发环境设定

本文假定:
1. 采用qgis官方发布的安装程序(如QGIS-OSGeo4W-2.18.13-1-Setup-x86.exe安装包)
2. 使用默认的安装位置,即C:\Program Files\QGIS 2.18,如指定到其他目录,请修改对应的设定。
3. 假定示例数据目录为D:\QGIS\数据\

第一:设定环境变量

SET OSGEO4W_ROOT=C:\Program Files\QGIS 2.18
SET QGIS_PREFIX=%OSGEO4W_ROOT%\apps\qgis
SET PATH=%QGIS_PREFIX%\bin;%OSGEO4W_ROOT%\bin
SET PYTHONPATH=%QGIS_PREFIX%\python;%OSGEO4W_ROOT%\apps\Python27
SET PYTHONHOME=%OSGEO4W_ROOT%\apps\Python27
SET GDAL_DATA=%OSGEO4W_ROOT%\share\gdal

即在cmd下执行上述命令,若路径不一致,请自行修改。

第二:运行一个样例

# -*- coding: utf-8 -*-
import os,os.path,sys

from qgis.gui import *
from qgis.core import *
from PyQt4 import QtGui

app = QtGui.QApplication([])
QgsApplication.setPrefixPath(os.environ['QGIS_PREFIX'],True)
QgsApplication.initQgis()

main_win = QtGui.QMainWindow()
frame = QtGui.QFrame(main_win)
main_win.setCentralWidget(frame)
grid_layout = QtGui.QGridLayout(frame)

map_canvas=QgsMapCanvas()
grid_layout.addWidget(map_canvas)
map_canvas.setCanvasColor(QtGui.QColor(255,255,255))
layer=QgsVectorLayer(ur'D:\qgis\数据\bou2_4p.shp','border','ogr')

QgsMapLayerRegistry.instance().addMapLayer(layer)
canvas_layer=QgsMapCanvasLayer(layer)
map_canvas.setLayerSet([canvas_layer])
map_canvas.zoomToFullExtent()

main_win.show()
# Need the following statement if running as a script
app.exec_()

可在前述cmd环境下运行python,将此代码粘贴进来运行。

第三,说明:
layer=QgsVectorLayer(ur'D:\qgis\数据\bou2_4p.shp','border','ogr')
这个语句,如目录名称中不含中文,则路径前的u可以移除。当然,也可以这样写:
layer=QgsVectorLayer(u'D:\\qgis\\数据\\bou2_4p.shp','border','ogr')
同时,建议在python下逐行执行来理解代码。

使用gnuplot批量画图

处理数据使用gnuplot画图,遇到一个需要批量画图的需求,即将2年的数据,以每28天一张图绘制,一共大概绘制26张左右。

在gnuplot中,也可以使用do循环来绘制,就是在处理时间变化的时候要注意,代码如下:

set xdata time
set timefmt "%Y-%m-%dT%H"
set xtics format "%Y-%m\n%H:%M" nomirror

set term png size 1600,1200
date1=strptime("%Y-%m-%dT%H",'2015-01-01T0')
do for [t=0:25] {
outfile = sprintf('shanghai-hourly-%03i.png',t)
set output outfile
set multiplot
set size 1,0.5
set origin 0,0.5
clear
date2=date1+(14*24-1)*3600
set xrange [date1:date2]
plot 'weibonum-shanghai-hour.txt' u 1:3 w lp t ''
set origin 0,0
clear
date1=date2+3600
date2=date1+(14*24-1)*3600
set xrange [date1:date2]
replot
unset multiplot
unset output
date1=date2+3600
}

Install psycopg2 on mac sierra

需要在我的mbp上进行数据入库测试,因此就需要安装psycopg2,但安装的时候一直有提示:

ld: library not found for -lssl

clang: error: linker command failed with exit code 1 (use -v to see invocation)

开始搜索以为库的位置不对,比如之前类似的问题:http://stackoverflow.com/questions/27264574/import-psycopg2-library-not-loaded-libssl-1-0-0-dylib

后来感觉不太对,又加上sierra关键词找,果然找到一个类似问题:
http://stackoverflow.com/questions/39767810/cant-install-psycopg2-package-through-pip-install-is-this-because-of-sierra
发现解决方法非常简单,就是安装xcode-select工具。

xcode-select –install

然后再安装psycopg2就没有任何问题了:

sudo pip install psycopg2

python下非常规utf8编码处理

最近在和微博页面打交道,发现微博返回的页面数据多数都是内嵌在javascript下的,而带来的后果就是其中的中文字符是json编码后的utf8编码。
而在python程序中获取页面后得到的结果大致有这样的字符:
"\u003Cp\u003E"
在python中这样可以直接打印出来:
print u"\u003Cp\u003E"
但作为一个变量,不能这样简单处理,需要进行编码转换:
str="\u003Cp\u003E"
print str.decode('unicode-escape')