Python处理临时文件

tempfile这个模块主要是用来创建临时文件和目录,用完后会自动删除,省的你自己去创建一个文件、使用这个文件、再删除这个过程了。其中比较常用的是TemporaryFile和NamedTemporaryFile。

import tempfile
import os
 
tmp1 = tempfile.TemporaryFile()   # 创建一个临时文件
type(tmp1)   # tempfile._TemporaryFileWrapper
tmp1.close()    # 关闭后,文件立即删除
 
tmp2 = tempfile.NamedTemporaryFile(delete=False) # 创建有名字的临时文件,且关闭后不立即删除
tmp2.name    # 'C:\Users\chenw\AppData\Local\Temp\tmpj9whdpr8'
os.path.exists(tmp2.name)   # True
tmp2.write("This is a tmp file!".encode())    # 不接收字符串(str),只能是字节流(bytes)
 
tmp2.seek(0)    # 调用read()函数前,需要调用seek()函数,指定读取指针的位置,参数是偏移量,0表示从头开始
tmp2.read()    # b'This is a tmp file!'   read()函数的返回值类型依然是bytes,而不是str
tmp2.close()    # 关闭后,文件不立即删除

Python发送邮件

Python提供了标准库smtplib用于发送邮件,整个过程非常简单,不足的地方是密码是明码。

import smtplib
from email.mime.text import MIMEText
 
#发件人
mail_from = "BioChen.com<admin@biochen.com>"
mail_host = "smtp.exmail.qq.com"
mail_usr = "admin@biochen.com"
mail_pwd = "pass_word"
 
#收件人
mail_to_addr = "pm.chenwen@qq.com"
 
#登录服务器
server = smtplib.SMTP(mail_host)
server.login(mail_usr,mail_pwd)
 
#邮件内容
content = 'this email is a test for python!'
msg = MIMEText(content,_subtype='plain')
msg['Subject'] = 'this email is a test for python!'
msg['From'] = mail_from
msg['To'] = mail_to_addr
 
#发送邮件
server.sendmail(mail_from, mail_to_addr, msg.as_string())
 
#关闭服务器
server.close()

网易和腾讯邮箱的SMTP服务器地址:

服务商 发件服务器 端口
网易163邮箱 smtp.163.com 25
网易企业邮 smtp.ym.163.com 25
腾讯QQ邮箱 smtp.qq.com 25
腾讯企业邮 smtp.exmail.qq.com 25

Google翻译API

Github上面其实有Google翻译的API,由于我国社会主义初级阶段的基本国情,直接拿来用好像行不通!

import requests
from bs4 import BeautifulSoup
 
def getHTMLText(url):
    try:
        r = requests.get(url, timeout=30)
        r.raise_for_status()
        return r.text
    except:
        print("Get HTML Text Failed!")
        return 0
 
def google_translate(to_translate, from_language="en", to_language="ch-CN"):
    #根据参数生产提交的网址
    base_url = "https://translate.google.cn/m?hl={}&sl={}&ie=UTF-8&q={}"
    url = base_url.format(to_language, from_language, to_translate)
 
    #获取网页
    html = getHTMLText(url)
    if html:
        soup = BeautifulSoup(html, "html.parser")
 
    #解析网页得到翻译结果
    try:
        result = soup.find_all("div", {"class":"t0"})[0].text
    except:
        print("Translation Failed!")
        result = ""
 
    return result
 
print(google_translate("Hello World!"))
 
#你好,世界

代码好像超级简单哈,有空的话我想把它做成一个库。有github的给个星星呗,鼓励一下!
https://github.com/wen-chen/PyTransl

Python图像库Pillow

PIL(Python Imaging Library Python图像库)是一个强大的图像处理标准库,功能强大却又简单易用。现在的名字叫做Pillow。

安装Pillow

pip3 install pillow

如果你使用的是Anaconda开发环境,自带Pillow库。值得注意的是,导入Pillow库时,库的名称是PIL。下面我们将用Pillow库做一些有意思的事情。

1. 图像手绘效果

from PIL import Image
import numpy as np
 
a = np.asarray(Image.open('./picture.jpg').convert('L')).astype('float')
 
depth = 10. 					#(0-100)
grad = np.gradient(a)				#取图像灰度的梯度值
grad_x, grad_y = grad 				#分别取横纵图像梯度值
grad_x = grad_x*depth/100.
grad_y = grad_y*depth/100.
A = np.sqrt(grad_x**2 + grad_y**2 + 1.)
uni_x = grad_x/A
uni_y = grad_y/A
uni_z = 1./A
 
vec_el = np.pi/2.2 			        #光源的俯视角度,弧度值
vec_az = np.pi/4. 			        #光源的方位角度,弧度值
dx = np.cos(vec_el)*np.cos(vec_az) 	        #光源对x 轴的影响
dy = np.cos(vec_el)*np.sin(vec_az) 	        #光源对y 轴的影响
dz = np.sin(vec_el) 			        #光源对z 轴的影响
 
b = 255*(dx*uni_x + dy*uni_y + dz*uni_z) 	#光源归一化
b = b.clip(0,255)
 
im = Image.fromarray(b.astype('uint8')) 	#重构图像
im.save('./picture2.jpg')

图像效果如下:

2.生成数字验证码

from PIL import Image, ImageDraw, ImageFont, ImageFilter
import random
 
#随机字母:
def rndChar():
    return chr(random.randint(48, 57))
 
#随机颜色1:
def rndColor():
    return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))
 
#随机颜色2:
def rndColor2():
    return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))
 
#240 x 60:
width = 60 * 4
height = 60
image = Image.new('RGB', (width, height), (255, 255, 255))
#创建Font对象:
font = ImageFont.truetype('ariblk.ttf', 40)
#创建Draw对象:
draw = ImageDraw.Draw(image)
#填充每个像素:
for x in range(width):
    for y in range(height):
        draw.point((x, y), fill=rndColor())
#输出文字:
for t in range(4):
    draw.text((60 * t + 10, 10), rndChar(), font=font, fill=rndColor2())
#模糊:
image = image.filter(ImageFilter.BLUR)
image.save('code.jpg', 'jpeg')

得到的数字验证码如下图:

Python运算符和优先级

运算符 说明
yield X 生成器函数结果(返回send()值)
lambda args1:X 匿名函数生成器(调用后返回X)
X if Y else Z 三元选择(当Y为真时计算X,否则计算Z)
X or Y 逻辑或
X and Y 逻辑与
not X 逻辑非
X in Y, X not in Y 成员是否在可迭代对象中
X is Y, X is not Y 对象等价测试
X Y, X >= Y 大小比较
X == Y, X != Y 相等运算符
X | Y 集合并
X ^ Y 集合对称差
X ^ Y 集合交
X << Y, X >> Y 将X左/右移Y位
X + Y, X – Y 加,减
X * Y, X / Y, X // Y, X % Y 乘,除,整除,取余
-X, +X 负,正
~X 按位非补(倒置)
X ** Y 乘方
X[i] 索引(序列,映射,其他)
X[i:j:k] 切片
X(args) 调用(函数,方法,类和其他可调用对象)
X.attr 属性引用
(…) 元组,表达式,生成器表达式
[…] 列表,列表内涵
{…} 字典,集合,字典与集合内涵

参考:
《Python袖珍指南》(第五版)

Python常用转义字符

转义字符 含义 转义字符 含义
\newline 忽略换行 \t 水平制表符
\\ 反斜杠(\) \v 竖直制表符
\’ 单引号(‘) \N{id} Unicode dbase id
\” 双引号(“) \uhhhh Unicode 16位十六进制
\a 蜂鸣(Bell) \Uhhhhhhhh Unicode 32位十六进制
\b 空格 \xhh Hex(最多两位数字)
\f 换页 \ooo Octal(达到三位数字)
\n 换行 \0 Null(非字符串结尾)
\r 回车 \other 非转义字符

这里的大部分转义字符跟linux系统保持一致!
\Uhhhhhhhh严格采用8个十六进制数字(h)。\u和\U只可以用在Unicode字符串文字中。

BED格式转GTF格式

# -*- coding: utf-8 -*-
"""
Created on Fri Dec 25 19:43:00 2015
 
@author: biochen
"""
 
import sys, getopt, csv
 
# get parameter
opts, args = getopt.getopt(sys.argv[1:], "hi:o:s:")
input_file = ""
output_file = ""
source = ""
for op, value in opts:
    if op == "-i":
        input_file = value
    elif op == "-o":
        output_file = value
    elif op == "-s":
        source = value
    elif op == "-h":
        print("Usage: python3 BED2GTF.py -i input.bed -o output.gtf -s source")
        sys.exit()
 
 
BED_in_file = open(input_file, "r")
GTF_out_file = open(output_file, "w")
BED = csv.reader(BED_in_file, dialect = "excel-tab")
GTF = csv.writer(GTF_out_file, dialect = "excel-tab", quotechar = "'")
 
for item in BED:
    transcript = []
    transcript.append(item[0])
    transcript.append(source)
    transcript.append("transcript")
    transcript.append(int(item[1]) + 1)
    transcript.append(int(item[2]) + 1)
    transcript.append(item[4])
    transcript.append(item[5])
    transcript.append(".")
    transcript.append('transcript_id "' + item[3] + '";')
    GTF.writerow(transcript)
    exon_number = int(item[9])
    exon_size = list(map(int, (filter(lambda x:x and len(x.strip()) > 0, item[10].split(",")))))
    exon_start = list(map(int, (filter(lambda x:x and len(x.strip()) > 0, item[11].split(",")))))
    for i in range(exon_number):
        exon = []
        exon.append(item[0])
        exon.append(source)
        exon.append("exon")
        exon.append(int(item[1]) + exon_start[i] + 1)
        exon.append(exon[3] + exon_size[i] - 1)
        exon.append(item[4])
        exon.append(item[5])
        exon.append(".")
        exon.append('transcript_id "' + item[3] + '\";')
        GTF.writerow(exon)
 
BED_in_file.close()
GTF_out_file.close()

GTF格式转BED格式

 # -*- coding: utf-8 -*-
"""
Created on Wed Dec 16 11:03:05 2015
 
@author: biochen
"""
 
import sys, getopt, csv, re
 
opts, args = getopt.getopt(sys.argv[1:], "hi:o:")
for op, value in opts:
    if op == "-i":
        GTF_in_File_Name = value
    elif op == "-o":
        BED_in_File_Name = value
    elif op == "-h":
        print("Usage: python3 GTF2BED.py -i input.gtf -o output.bed")
        sys.exit()
 
GTF_in_file = open(GTF_in_File_Name, "r")
BED_out_file = open(BED_in_File_Name, "w")
GTFs = csv.reader(GTF_in_file, dialect = "excel-tab")
BEDs = csv.writer(BED_out_file, dialect = "excel-tab")
 
transcripts = {}
for GTF in GTFs:
    if GTF[2] == "exon":
        transcript_id = re.findall('transcript_id "([^;]*)"', GTF[8])[0]
        if transcript_id in transcripts:
            transcripts[transcript_id][6].append([int(GTF[3]), int(GTF[4])])
        else:
            transcripts[transcript_id] = []
            transcripts[transcript_id].append(GTF[0])
            transcripts[transcript_id].append(GTF[3])
            transcripts[transcript_id].append(GTF[4])
            transcripts[transcript_id].append(GTF[5])
            transcripts[transcript_id].append(GTF[6])
            transcripts[transcript_id].append(transcript_id)
            transcripts[transcript_id].append([[int(GTF[3]), int(GTF[4])]])
 
for transcript in transcripts:
    transcripts[transcript][6].sort()
    transcript_start = transcripts[transcript][6][0][0]
    transcript_end = transcripts[transcript][6][len(transcripts[transcript][6]) - 1][1]
    exon_sizes = ""
    exon_starts = ""
    for exon in transcripts[transcript][6]:
        exon_size = exon[1] - exon[0] + 1
        exon_start = exon[0] - transcript_start
        exon_sizes = exon_sizes + str(exon_size) + ","
        exon_starts = exon_starts + str(exon_start) + ","
    BED = []
    BED.append(transcripts[transcript][0])
    BED.append(transcript_start - 1)
    BED.append(transcript_end)
    BED.append(transcripts[transcript][5])
    BED.append(transcripts[transcript][3])
    BED.append(transcripts[transcript][4])
    BED.append(transcript_start - 1)
    BED.append(transcript_end)
    BED.append("0, 0, 0")
    BED.append(len(transcripts[transcript][6]))
    BED.append(exon_sizes)
    BED.append(exon_starts)
    BEDs.writerow(BED)
 
GTF_in_file.close()
BED_out_file.close()

Python计算Rank(秩)

在统计学中,有时候我们需要求一组数据的Rank,如非参检验、Spearman相关性等。Rank中文意思叫做顺序,更专业点的叫法是”秩”。这里介绍一下用Python求Rank。
先看一个简单的例子:

>>> a = [1.0, 5.6, 3.5, 9.7, 7.8]
>>> # rank_a = [1, 3, 2, 5, 4]
...
>>> rank_a = sorted(range(len(a)), key = a.__getitem__)
>>> rank_a
[0, 2, 1, 4, 3]
>>> rank_a = [i + 1 for i in rank_a]
>>> rank_a
[1, 3, 2, 5, 4]

上面的例子中,列表a中的元素是没有重复的,直接排序即可。如果有重复元素怎么办呢?最简单的办法是使用SciPy提供的rankdata()函数。

>>> from scipy.stats import rankdata
>>> rankdata([0, 2, 3, 2])
array([ 1. ,  2.5,  4. ,  2.5])
>>> rankdata([0, 2, 3, 2], method='min')
array([ 1,  2,  4,  2])
>>> rankdata([0, 2, 3, 2], method='max')
array([ 1,  3,  4,  3])
>>> rankdata([0, 2, 3, 2], method='dense')
array([ 1,  2,  3,  2])
>>> rankdata([0, 2, 3, 2], method='ordinal')
array([ 1,  2,  4,  3])

rankdata()函数返回一个array对象,默认的方法是average,即相同元素的Rank值取算术平均数,同时rankdata()函数还提供了其他方法。
如果觉得安装SciPy库太麻烦,我们也可以自己实现。下面的代码计算重复元素的Rank使用的方法是average,返回一个列表。

def rank_simple(vector):
    return sorted(range(len(vector)), key=vector.__getitem__)
 
def rankdata(vector):
    n = len(vector)
    ivec = rank_simple(vector)
    svec = [vector[rank] for rank in ivec]
    sumranks = 0
    dupcount = 0
    newvector = [0] * n
    for i in range(n):
        sumranks = sumranks + i
        dupcount = dupcount + 1
        if i == n - 1 or svec[i] != svec[i + 1]:
            averank = sumranks / float(dupcount) + 1
            for j in range(i - dupcount + 1, i + 1):
                newvector[ivec[j]] = averank
            sumranks = 0
            dupcount = 0

Python列表推导式

Python进阶之一就是学会写列表推导式。列表推导式用较为优雅的方式生成列表,从而避免冗余代码,不过对于新手来讲,代码的可读性不高。我们先看下面一段示例。

>>>a = [1, 2, 3, 4]
>>>b = [item * 2 for item in a]
>>>b
[2, 4, 6, 8]

上述代码将一个列表中每一个元素加倍生成一个新的列表,可以写成如下更容易理解的形式:

>>>a = [1, 2, 3, 4]
>>>b = []
>>>for item in a:
...     b.append(item * 2)
...
>>>b
[2, 4, 6, 8]

结果是一样的,但是列表推导式所需的代码更少。如果我们只想保留偶数并加倍,可以这么写:

>>>a
[1, 2, 3, 4]
>>>b = [item * 2 for item in a if item % 2 == 0]
>>>b
[4, 8]

总结一下,Python列表推导式的模式为[expression for item in sequence if conditions]。列表推导式放在[]中;首先是一个表达式,定义了对每一个元素要做什么;接下来是一个for循环,从一个序列中依次拿出一个元素;最后是if条件,可以没有if条件。[]改为()得到的是一个生成器(generator),改为{}得到一个字典或者集合。
用列表推导式可以写出更有创意的代码,当然如果代码很难被读懂,应该尽量实现更好可读性的代码。可读性高的代码才更加具有生命力。