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')

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下逐行执行来理解代码。

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')

shell下python脚本的输出转向

一个用python写的脚本,在本地测试的时候用python的print输出了一些状态信息,用于观测程序运行的状况。脚本自身比较耗时(中间故意设置了延时)。
在部署到服务器上后,需要后台运行,因此就想当然的转向输出到一个文本log中:
python script.py > output.log &
结果发现log文件一直是空白(程序在持续运行中),但正常应该是有文本记录的。结果网上搜索才发现,python脚本默认是在脚本整个执行完成后才输出的。(参考:https://unix.stackexchange.com/questions/182537/write-python-stdout-to-file-immediately/182542#182542
当然,知道问题后解决方案也很简单:
python -u script.py > output.log &

Compile & install GRASS 6.4 on ubuntu intrepid

首先,需要自己重新编译GDAL,目前UBUNTU源里的GDAL有BUG。
然后,从svn中下载grass 6.4:

svn co https://svn.osgeo.org/grass/grass/branches/develbranch_6 grass-6.4
cd grass-6.4/debian
svn://svn.debian.org/pkg-grass/packages/grass/branches/6.4/debian debiangis
mv debiangis/* .

目前,这个DEB控制还有点小问题,需要自己作些修改:

nano grass.conf

把路径修改为:

/usr/lib/grass64/lib

然后修改grass-preview-doc.links,修改为:

usr/share/doc/grass-preview-doc/html usr/lib/grass64/docs/html

还需要连接一个so库:

locate _gdi_.so

我的机器上有两个地址,一个是python 2.4,一个是python 2.5,我选择了python 2.5的地址,然后作了个连接:

sudo ln -s /usr/lib/python2.5/site-packages/wx-2.8-gtk2-unicode/wx/_gdi_.so /usr/loca/lib/libgdi.so

然后就可以编译了:

debuild binary

然后就可以安装了,你若不想安装,可以使用我已经编译好的,(添加我自己的源):

http://ubuntu.westgis.ac.cn/ubuntu

然后sudo aptitude install grass-preview就可以了。

如要安装文档:

sudo aptitude install grass-preview-doc
sudo mkdir /usr/lib/grass64/docs
sudo ln -s /usr/share/doc/grass-preview-doc/html /usr/lib/grass64/docs/