违法℃玩家 发表于 2018-8-5 14:21:36

Python操作小结(mysql、txt\json、crontab、http)

  有段时间没有使用python了,对它的语法有点生疏,花了几个小时熟悉,期间发现很多小细节不清楚。为了下次能快速上手,避免重复犯错,我将python使用过程中的一些问题在这篇博文中记录小结一下,主要内容涉及到python操作mysql数据库,python发送http请求,解析txt文本,解析JSON字符串,crontab执行python脚本,等等。(注:我用的是python2.7版本)
  为方便操作,建议在系统环境变量path里面添加python的安装路径,比如我的是D:\Python27。
  一、添加第三方模块module,并导入模块
  在windowns里面,可以先下载模块对应的包文件,放到python默认的模块文件夹下(./python2.7/Lib/site-packages/)。然后在cmd中进入模块的解压文件,执行python setup.py install。(注意:如果事先没有添加python安装路径到环境变量里,是不能执行这个命令的)
  在ubuntu里,以root用户权限执行 easy_install module_name,便可。
  在linux系统里,执行 sudo yum install
module_name,便可。
  有些模块需要下载对应的压缩包,解压后进入包下,找到setup.py,执行
python#{版本号} setup.py install 进行安装  python的脚本文件里面,可以导入其他脚本文件,并引用其中的方法和参数,使用关键字import。如下:
  import os,glob,sys
  注意:要想到添加的模块成功import导入,需要重启python 的IDLE,否则虽然可以在cmd命令行成功import,却不能在IDLE中import,会提示找不到module。
  二、基础数据类型和语法
  1、普通变量定义
  python 作为脚本型语言,对变量的定义很宽松,不用为变量特定申明其类型,类似于jsp页面中的变量定义,直接是    变量名=...    即可。
  输出字符和整型变量拼接的内容时,需要把整型转换成字符型,如
  i=10
  print 'out:'+i   会报错:TypeError: cannot concatenate 'str' and 'int' objects
  需要更改成:
  print 'out:'+str(i)
  2、数组变量定义
  数组变量定义,在=号后面加上中括号,中括号中可以指定数组长度。如:phoneList = []。往数组中添加值,用的是数组的append()方法;获取数组某位的值,用: phoneList即可。获取数组的长度,可以用 len(List)方法。数组排序方法:phoneList.sort()
  对数组使用sorted(array),能直接排序数组。如果是字符串类型,则按首字母排序,如:1, 10, 12, 2, 23, 3 ...
  3、字典变量的定义
  (1)字典定义
  dict={}即可。
  获取字典的所有Kye值:    dict.keys()
  根据key值取字典value:    v=name_dict
  判断某个key是否在字典里:
a={'a':1,'b':2,'c':3}  
if 'b' in a:
  
    print a['b']
  (2)字典排序
  按value值大小排序:
  ret_list = sorted(d.items(),key=lambda item:item)
  d.items()表示将字典d转换成元组列表,key=lambda item:item 表示选取每个元组中第二个元素作为比较对象。此时返回的结果是一个元组列表
  4、字符串变量
  字符串对象包含了一些私有的方法,如
  (1)以某类分隔符对字符串进行分割的 .split(';') 方法;去除字符串首位的字符的 .strip('--')方法;
  (2)截取字符串一段:sStr1 = sStr2
  (3)str类型字符串与unicode类型字符串转换
string和unicode都有decode()和encode()方法。  
decode方法是将string转换成unicode;
  
encode方法是将unicode转换成string;
  
contentList = " ".join()#unicode类型
  

  
print contentList.__class__
  
contentList = contentList.encode('utf-8')
  
print contentList.__class__
  5、异常处理
  python可以使用try...except处理异常,例如:
sql='select * from table'  
try:
  
    cur.execute('set NAMES utf8')
  
    cur.execute(sql)
  
    con.commit()
  
except Exception, e:
  
    print Exception,":",e
  
    print sql
  6、python文件头申明
#!/usr/bin/python  
#-*- coding:utf-8 -*-
  
#encoding=utf-8
  
import os,sys
  
reload(sys)
  
sys.setdefaultencoding("utf-8")
  7、对象声明和使用
#定义对象  
class LoginObj:
  
    app_id=''
  
    corp_id=''
  
    corp_name=''
  
    phone=''
  
#对象使用
  
    loginObj=LoginObj()
  
    loginObj.corp_id='aaa'
  
    ...
  判断NoneType类型的数据: if st is None: print("st is none")
  NoneType类型数据不能用len(st)==0 或 st=='' 来判断。
  三、读取数据库表
  1、引入MySQLdb包。
  windows下,下载这个包的exe文件,直接点击安装即可;
  linux下,可以用命令sudo yum install
MySQL-python 安装。
  引入包:import MySQLdb as mdb
  MySQLdb连接mysql数据库,只在2.x版本中支持,推荐使用2.7版本。
  2、连接mysql数据库
  需要指定数据库服务器地址ip、数据库用户名和秘密、需访问的数据库名以及默认字符编码。如:
  conn = mdb.connect('hostIp','root','view','db_test',charset='utf8')表示访问hostIp中的db_test数据库,用户名root,密码view,设置字符编码是utf8。
  由于mysql默认数据库服务器端口是3306,如果你的端口不是这个,就需要在连接时指定端口(端口号是int 型,不需加引号),如:
  conn = mdb.connect('hostIp','user_name','password','db_name',port,charset='utf8')
  3、使用游标,来获取数据库查询结果的每一行
  cur = conn.cursor()#先定义一个游标
  sql = "select ..."#定义sql语句
  cur.execute("set NAMES utf8")#设定sql语句中的参数的字符编码是utf8
  cur.execute(sql)   #执行sql查询语句。
  conn.commit()   #提交sql语句,一定要加上。
  4、获取查询结果中的每一行结果数据
  rows= cur.fetchall()#rows是很多行的一个集合
  val = row#row 是rows中的一行。使用循环获取每一行。
  四、for循环语句, 子语句必须要缩进一个tab键。
  退出循环时,语句与for语句块间隔一行以方便区分。如下:
  for row in rows:
  print (row)
  print ("out of for block")
  五、操作文件
  1、文件路径,如下:
  windows中: path=r'E:\tmp-excel'+'\\'   (字符串前的字母‘r’的意思,表示一个原始字符串)
  Linux中:file_path='/usr/local/test/'
  对于最后一个路径字符串以\结尾的,需要使用转义字符形式 '\\',第一个 \ 是转义标识符,表示接下来的一个字符是真实字符。
  2、读取路径下的文件和内容,需要导入 os包和glob包。
  python使用 os.chdir(path) 跳转到指定path目录下;
  然后用 glob.glob('*.txt.???'),模糊匹配文件名满足*.txt???格式的文件(*号表示匹配任意个字符,?号表示匹配单个任意字符),并返回文件名的数组对象fileList。
  使用fo = open(fileName) 方法打开文件, lines = fo.readlines() 按行读取文件全部内容。(ps: 虽然我每行都以 '\r' 字符结尾的,但python可能会将整个文件内容只作为一行,我就是这种情况。)为了获得每一行的数据,我将整个一行用 .split('\r') 进行拆分,再进行处理。
  如果需要对路径下的文件排序后再处理,可以直接使用数组排序方法fileList.sort(), 对文件名数组排序。
  3、更改文件名
  os.rename(oldName,newName)
  六、提交http请求:
  (1)使用httplib2提交http GET请求,并获取响应数据
import httplib2  
url=' httplib2.Http('.cache')#设置使用缓存
  
h=httplib2.Http()#不使用缓存response,content=h.request(url)
  
print '%s' %(content)
  (2)使用httplib提交http POST请求,并获取响应数据
import httplib  
def postToNewUser(userJArray,host,port,url,token):
  
   headers={'Content-Type': 'application/x-www-form-urlencoded; ','Authorization':'Bearer '+token,'Accept':'application/vnd.yiqiapp-cn.v1+json','User-Agent':'yiqiapp/android/1.0'}
  
   conn=httplib.HTTPConnection(host,port)
  
   jparam=urllib.urlencode({'action':'import','users':userJArray})
  
   conn.request('POST',url,jparam,headers)
  
   rsp=conn.getresponse()
  
   data=rsp.read()
  
   param=json.loads(data)
  
   return param
  注:
  对于包含汉字、空格和其他特殊字符的URL,需要进行编码,使用urllib.quote(param)可以对指定的参数单独编码,如:
  urllib.quote('2016-08-01 00:00:00')将时间字符串编码成:2016-08-01%2000%3A00%3A00
  post请求中的参数,使用urllib.urlencode(...)进行封装成标准格式。
  七、python解析json数据
#导入模块:json  
import json
  
import httplib2
  
url='http://api.umeng.com/apps?auth_token=fdsfsdolnmjfsolf'
  
h=httplib2.Http('.cache')
  
response,content=h.request(url)
  
#s是一个数组:[{appkey:xxxx,category:aaaa,name:ddd},{appkey:eee,category:bd,name:kkk}...]
  
s=json.loads(content)
  
print len(s)
  
for i in s:
  
    print i['appkey']
#json数组操作  
import demjson
  
jvalueList=[]
  
jsonArray=[]
  
jsonObj={}
  
jsonObj['name']=user.name
  
jsonObj['phone']=user.phone
  
try:
  
    jsonArray.append(jsonObj)
  
except Exception , e:
  
    print 'continue'
  
#print jsonArray['name']
  
try:
  
    #将json数组转换成字符串,去掉'u'标记
  
    jvalue=demjson.encode(jsonArray)
  
    jvalueList.append(jvalue)
  
    userNum=userNum+1
  
except Exception , e:
  
    print jvalue
  八、在crontab中定时执行python脚本
  1. crontab执行定时任务的方法,我就不做过多说明了,就是指定定时执行的时间、需执行的脚本命令。举个例子,每天8点50分,执行日志解析的脚本,将结果保存到指定文件中:
  50 8 * * * /usr/local/bin/python   /root/python_scripts/parse_log.py > /root/results/test.txt &
  2. 可能会出现的问题
  (1)一个最可能出现的问题就是,上面的语句 在shell中执行没有问题,但是在crontab中却不能执行,并可能提示某些依赖的module无法导入:importError: No module named ....
  产生这个问题的最可能的原因是,crontab和shell中执行python时的版本不一致。我们可以通过一下方法进行验证:
  首先,在shell中执行:import sys,然后执行print sys.path,从系统路径当中找到当前shell使用的python版本。
  ['', '/usr/local/lib/python2.7/site-packages/setuptools-12.0.5-py2.7.egg', '/usr/local/lib/python2.7/site-packages/gunicorn-19.1.1-py2.7.egg'......
  然后,在parse_log.py中加入import sys和print sys.path 两行,在crontab中设定定时任务,如举例中的语句。执行结果可能会如下:
  ['', '/usr/local/lib/python2.6/site-packages/setuptools-12.0.5-py2.6.egg', '/usr/local/lib/python2.6/site-packages/gunicorn-19.1.1-py2.6.egg'......
  我们发现crontab和shell执行python时引用的版本不一致,而提示无法加载的模块可能在某个版本之后才新增进来的,因此出现了无法加载模块的问题。
  那么,解决的方法是:在crontab中使用全路径指定引用的python版本,即:
  50 8 * * * /usr/local/bin/python2.7 /root/python_scripts/parse_log.py > /root/results/test.txt &
  需要说明的是,为避免这类问题的出现,我们在设置crontab定时任务时,最后都使用全路径。
  代码示例:
  这次写的的代码如下:
  一、读取txt文件
#!/usr/bin/python  
#coding=utf-8
  
# -*- coding: utf-8 -*-
  
import os,glob,sys
  
phoneList = []
  
path=r'E:\tmp-excel'+'\\'
  
os.chdir(path)
  
sumJ=0
  
for fname in glob.glob('*.txt'):
  
    fo=open(fname)
  
    lines=fo.readlines()
  
    j=0
  
    print (fname)
  
    for line in lines:
  
      line=line.split('\r')
  
      for l in line:
  
            l=l.split(',,')
  
            phoneList.append(l)
  
            #print (l)
  
            j=j+1
  
    print (j)
  
    sumJ=sumJ+j
  
    print ("total phoneNo is :",len(phoneList))
  
print ("total phoneNo is :",sumJ)
页: [1]
查看完整版本: Python操作小结(mysql、txt\json、crontab、http)