python-other
web压侧
# coding=utf-8
import urllib
import urllib2
import cookielib
import threading
import time
from Queue import Queue
from time import sleep
THREAD_NUM = 100 # 并发线程总数
ONE_WORKER_NUM = 10000 # 每个线程的循环次数
LOOP_SLEEP = 0.5 # 每次请求时间间隔(秒)
# 出错数
ERROR_NUM = 0
requrl = "http://cs.dachuizichan.com/login.do"
test_data = {
'loginid':'17326800227',
'password':'111111',
'rand':'1111'
}
test_data_urlencode = urllib.urlencode(test_data)
header = {
"Host" : "cs.dachuizichan.com",
"Referer" : "http://cs.dachuizichan.com/manage/frame.do",
"User-Agent": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/54.0.2840.71 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded"
}
cookieJar = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookieJar))
req = urllib2.Request(requrl, test_data_urlencode,header)
result = opener.open(req)
# for key in header:
# req.add_header(key, header[key])
def doWork(index):
t = threading.currentThread()
try:
result2 = opener.open("http://cs.dachuizichan.com/manage/myDebtor/list.do")
print result2.read()
except urllib2.URLError,e:
print "["+t.name+" "+str(index)+"] "
print e
global ERROR_NUM
ERROR_NUM += 1
def working():
t = threading.currentThread()
print "["+t.name+"] Sub Thread Begin"
i = 0
while i < ONE_WORKER_NUM:
i += 1
doWork(i)
sleep(LOOP_SLEEP)
print "["+ t.name+"] Sub Thread End"
def main():
#doWork(0)
#return
t1 = time.time()
Threads = []
# 创建线程
for i in range(THREAD_NUM):
t = threading.Thread(target=working, name="T"+str(i))
t.setDaemon(True)
Threads.append(t)
for t in Threads:
t.start()
for t in Threads:
t.join()
print "main thread end"
t2 = time.time()
print "========================================"
#print "URL:", PERF_TEST_URL
print "任务数量:", THREAD_NUM, "*", ONE_WORKER_NUM, "=", THREAD_NUM*ONE_WORKER_NUM
print "总耗时(秒):", t2-t1
print "每次请求耗时(秒):", (t2-t1) / (THREAD_NUM*ONE_WORKER_NUM)
print "每秒承载请求数:", 1 / ((t2-t1) / (THREAD_NUM*ONE_WORKER_NUM))
print "错误数量:", ERROR_NUM
if __name__ == "__main__":
main()
一行python
打印心形
print'\n'.join([''.join([('PYTHON!'[(x-y)%7]if((x*0.05)**2+(y*0.1)**2-1)**3-(x*0.05)**2*(y*0.1)**3<=0 else' ')
for x in range(-30,30)])for y in range(15,-15,-1)])
99乘法表
print '\n'.join([' '.join(['%s*%s=%-2s' % (y,x,x*y) for y in range(1,x+1)]) for x in range(1,10)])
斐波那契数列
print [x[0] for x in [ (a[i][0], a.append((a[i][1], a[i][0]+a[i][1]))) for a in ([[1,1]], ) for i in xrange(100) ]]
8皇后
_=[__import__('sys').stdout.write("\n".join('.' * i + 'Q' + '.' * (8-i-1) for i in vec) + "\n===\n") for vec
in __import__('itertools').permutations(xrange(8)) if 8 == len(set(vec[i]+i for i in xrange(8))) ==
len(set(vec[i]-i for i in xrange(8)))]
打印自己
_='_=%r;print _%%_';print _%_
print(lambda x:x+str((x,)))('print(lambda x:x+str((x,)))',)
斐波那契数列
# coding:utf-8
def fib(n):
"""公式法"""
from math import sqrt, pow
return int(1/sqrt(5)*(pow((1+sqrt(5))/2,n) - pow((1-sqrt(5))/2,n)))
def fib2(n):
"""累加,使用之前计算的数"""
if n == 0:
return 0
elif n == 1:
return 1
firstnum = 0
secondnum = 1
fibnum = 0
cnt = 1
while cnt < n:
fibnum = firstnum + secondnum
firstnum ,secondnum = secondnum, fibnum
cnt += 1
return fibnum
def fib3(n):
"""列表计算追加,简洁"""
begin = [1, 1]
for count in xrange(1, n-2):
begin.append(begin[-1]+begin[-2])
return begin
def fib4(n):
"""递归计算"""
if n <= 1:
return n
else:
return fib4(n - 1) + fib4(n - 2)
# fib1 fib2 fib4
for i in range(1, 10):
print fib4(i)
# fib3
print fib3(10)
迭代器生成器
在了解Python的数据结构时,容器(container)、可迭代对象(iterable)、迭代器(iterator)、生成器(generator)、
列表/集合/字典推导式(list,set,dict comprehension)众多概念参杂在一起,难免让初学者一头雾水,我将用一篇文章试
图将这些概念以及它们之间的关系捋清楚。
relations
容器(container)
容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not in关键字判断元素是否包含在容器中。
通常这类数据结构把所有的元素存储在内存中(也有一些特列并不是所有的元素都放在内存)在Python中,常见的容器对象有:
list, deque, ....
set, frozensets, ....
dict, defaultdict, OrderedDict, Counter, ....
tuple, namedtuple, …
str
容器比较容易理解,因为你就可以把它看作是一个盒子、一栋房子、一个柜子,里面可以塞任何东西。从技术角度来说,当它可以用来询问
某个元素是否包含在其中时,那么这个对象就可以认为是一个容器,比如 list,set,tuples都是容器对象:
>>> assert 1 in [1, 2, 3] # lists
>>> assert 4 not in [1, 2, 3]
>>> assert 1 in {1, 2, 3} # sets
>>> assert 4 not in {1, 2, 3}
>>> assert 1 in (1, 2, 3) # tuples
>>> assert 4 not in (1, 2, 3)
询问某元素是否在dict中用dict的中key:
d = {1: 'foo', 2: 'bar', 3: 'qux'}
assert 1 in d
assert 'foo' not in d # 'foo' 不是dict中的元素
尽管绝大多数容器都提供了某种方式来获取其中的每一个元素,但这并不是容器本身提供的能力,而是可迭代对象赋予了容器这种能力,
当然并不是所有的容器都是可迭代的,比如:Bloom filter,虽然Bloom filter可以用来检测某个元素是否包含在容器中,但是并不能从
容器中获取其中的每一个值,因为Bloom filter压根就没把元素存储在容器中,而是通过一个散列函数映射成一个值保存在数组中。
可迭代对象(iterable)
刚才说过,很多容器都是可迭代对象,此外还有更多的对象同样也是可迭代对象,比如处于打开状态的files,sockets等等。但凡是可以
返回一个迭代器的对象都可称之为可迭代对象,听起来可能有点困惑,没关系,先看一个例子:
x = [1, 2, 3]
y = iter(x)
z = iter(x)
next(y) 1
next(y) 2
next(z) 1
type(x)
<class 'list'>>>> type(y)
<class 'list_iterator'>
这里x是一个可迭代对象,可迭代对象和容器一样是一种通俗的叫法,并不是指某种具体的数据类型,list是可迭代对象,dict是可迭代对象,
set也是可迭代对象。y和z是两个独立的迭代器,迭代器内部持有一个状态,该状态用于记录当前迭代所在的位置,以方便下次迭代的时候获
取正确的元素。迭代器有一种具体的迭代器类型,比如list_iterator,set_iterator。可迭代对象实现了__iter__和__next__方法
(python2中是next方法,python3是__next__方法),这两个方法对应内置函数iter()和next()。__iter__方法返回可迭代对象本身,
这使得他既是一个可迭代对象同时也是一个迭代器。
当运行代码:
x = [1, 2, 3]
for elem in x:
...
实际执行情况是:
iterable-vs-iterator.png
反编译该段代码,你可以看到解释器显示地调用GET_ITER指令,相当于调用iter(x),FOR_ITER指令就是调用next()方法,不断地获
取迭代器中的下一个元素,但是你没法直接从指令中看出来,因为他被解释器优化过了。
import dis
>>> x = [1, 2, 3]
>>> dis.dis('for _ in x: pass')
1 0 SETUP_LOOP 14 (to 17)
3 LOAD_NAME 0 (x)
6 GET_ITER
>> 7 FOR_ITER 6 (to 16)
10 STORE_NAME 1 (_)
13 JUMP_ABSOLUTE 7
>> 16 POP_BLOCK
>> 17 LOAD_CONST 0 (None)
20 RETURN_VALUE
迭代器(iterator)
那么什么迭代器呢?它是一个带状态的对象,他能在你调用next()方法的时候返回容器中的下一个值,任何实现了__next__()
(python2中实现next())方法的对象都是迭代器,至于它是如何实现的这并不重要。
所以,迭代器就是实现了工厂模式的对象,它在你每次你询问要下一个值的时候给你返回。有很多关于迭代器的例子,比如
itertools函数返回的都是迭代器对象。
生成无限序列:
from itertools import count
counter = count(start=13)
print next(counter) # 13
print next(counter) # 14
from itertools import cycle
colors = cycle(['red', 'white', 'blue'])
next(colors) # 'red'
next(colors) # 'white'
next(colors) # 'blue'
next(colors) # 'red'
from itertools import islice
limited = islice(colors,0,4)
print list(limited)
# ['white', 'blue', 'red', 'white']
为了更直观地感受迭代器内部的执行过程,我们自定义一个迭代器,以斐波那契数列为例:
class Fib:
def __init__(self):
self.prev = 0
self.curr = 1
def __iter__(self):
return self
def next(self):
value = self.curr
self.curr += self.prev
self.prev = value
return value
f = Fib()
print list(islice(f,0,10))
Fib既是一个可迭代对象(因为它实现了__iter__方法),又是一个迭代器(因为实现了next方法)。实例变量prev和curr用户维护迭
代器内部的状态。每次调用next()方法的时候做两件事:
为下一次调用next()方法修改状态
为当前这次调用生成返回结果
迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。
生成器(generator)
生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的
类一样写__iter__()和__next__()方法了,只需要一个yiled关键字。 生成器一定是迭代器(反之不成立),因此任何生成器也是以一
种懒加载的模式生成值。用生成器来实现斐波那契数列的例子是:
def fib(n):
prev, curr = 0, 1
while prev < n:
yield curr
prev, curr = curr, curr + prev
>>> print [x for x in fib(10)]
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
fib就是一个普通的python函数,它特需的地方在于函数体中没有return关键字,函数的返回值是一个生成器对象。当执行f=fib()返回
的是一个生成器对象,此时函数体中的代码并不会执行,只有显示或隐示地调用next的时候才会真正执行里面的代码。
生成器在Python中是一个非常强大的编程结构,可以用更少地中间变量写流式代码,此外,相比其它容器对象它更能节省内存和CPU,当然
它可以用更少的代码来实现相似的功能。现在就可以动手重构你的代码了,但凡看到类似:
def something():
result = [] for ... in ...:
result.append(x) return result
都可以用生成器函数来替换:
def iter_something():for ... in ...: yield x
生成器表达式(generator expression)
生成器表达式是列表推倒式的生成器版本,看起来像列表推导式,但是它返回的是一个生成器对象而不是列表对象。
a = (x*x for x in xrange(10))
print type(a)
# <type 'generator'>
print sum(a)
# 285
执行系统命令
commands
import commands
commands.getstatusoutput(cmd) 返回(status, output)
commands.getoutput(cmd) 只返回输出结果
os
import os
os.system("echo \"Hello World\"")
or
print os.popen('ls -lt').read()
传shell的参数
import os
var=123或var='123'
os.environ['var']=str(var) #environ的键值必须是字符串
os.system('echo $var')
import os
var='123'
os.popen('wc -c', 'w').write(var)
fabric
pip install fabric
fab -f fabfile -l 显示定义好的任务函数名
fab -f fabfile func 执行相应函数
文件打包上传---------------------------------------
#!/usr/bin/env python
#coding:utf-8
from fabric.api import *
from fabric.context_managers import *
from fabric.contrib.console import confirm
env.user='root'
env.hosts=['192.168.1.21','192.168.1.22']
env.password='LKs934jh3'
@task
@runs_once
def tar_task(): #本地打包任务函数,只限执行一次
with lcd("/data/logs"):
local("tar -czf access.tar.gz access.log")
@task
def put_task(): #上传文件任务函数
run("mkdir -p /data/logs")
with cd("/data/logs"):
with settings(warn_only=True): #put(上传)出现异常时继续执行,非终止
result = put("/data/logs/access.tar.gz", "/data/logs/access.tar.gz")
if result.failed and not confirm("put file failed, Continue[Y/N]?"):
abort("Aborting file put task!") #出现异常时,确认用户是否继续,(Y继续)
@task
def check_task(): #校验文件任务函数
with settings(warn_only=True): #本地local命令需要配置capture=True才能捕获返回值
lmd5=local("md5sum /data/logs/access.tar.gz",capture=True).split(' ')[0]
rmd5=run("md5sum /data/logs/access.tar.gz").split(' ')[0]
if lmd5==rmd5: #对比本地及远程文件md5信息
print "OK"
else:
print "ERROR"
@task
def go():
tar_task()
put_task()
check_task()
LNMP安装--------------------------------------------------
#!/usr/bin/env python
#coding:utf-8
from fabric.colors import *
from fabric.api import *
env.user='root'
env.roledefs = { #定义业务角色分组
'webservers': ['192.168.1.21', '192.168.1.22'],
'dbservers': ['192.168.1.23']
}
env.passwords = {
'root@192.168.1.21:22': 'SJk348ygd',
'root@192.168.1.22:22': 'KSh458j4f',
'root@192.168.1.23:22': 'KSdu43598'
}
@roles('webservers') #webtask任务函数引用'webservers'角色修饰符
def webtask(): #部署nginx php php-fpm等环境
print yellow("Install nginx php php-fpm...")
with settings(warn_only=True):
run("yum -y install nginx")
run("yum -y install php-fpm php-mysql php-mbstring php-xml php-mcrypt php-gd")
run("chkconfig --levels 235 php-fpm on")
run("chkconfig --levels 235 nginx on")
@roles('dbservers') # dbtask任务函数引用'dbservers'角色修饰符
def dbtask(): #部署mysql环境
print yellow("Install Mysql...")
with settings(warn_only=True):
run("yum -y install mysql mysql-server")
run("chkconfig --levels 235 mysqld on")
@roles ('webservers', 'dbservers') # publictask任务函数同时引用两个角色修饰符
def publictask(): #部署公共类环境,如epel、ntp等
print yellow("Install epel ntp...")
with settings(warn_only=True):
run("rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm")
run("yum -y install ntp")
def deploy(): #以实现不同角色执行不同的任务函数
execute(publictask)
execute(webtask)
execute(dbtask)
代码发布--------------------------------------------------
#!/usr/bin/env python
#coding:utf-8
from fabric.api import *
from fabric.colors import *
from fabric.context_managers import *
from fabric.contrib.console import confirm
import time
env.user='root'
env.hosts=['192.168.1.21','192.168.1.22']
env.password='LKs934jh3'
env.project_dev_source = '/data/dev/Lwebadmin/' #开发机项目主目录
env.project_tar_source = '/data/dev/releases/' #开发机项目压缩包存储目录
env.project_pack_name = 'release' #项目压缩包名前缀,文件名为release.tar.gz
env.deploy_project_root = '/data/www/Lwebadmin/' #项目生产环境主目录
env.deploy_release_dir = 'releases' #项目发布目录,位于主目录下面
env.deploy_current_dir = 'current' #对外服务的当前版本软链接
env.deploy_version=time.strftime("%Y%m%d")+"v2" #版本号
@runs_once
def input_versionid(): #获得用户输入的版本号,以便做版本回滚操作
return prompt("please input project rollback version ID:",default="")
@task
@runs_once
def tar_source(): #打包本地项目主目录,并将压缩包存储到本地压缩包目录
print yellow("Creating source package...")
with lcd(env.project_dev_source):
local("tar -czf %s.tar.gz ." % (env.project_tar_source + env.project_pack_name))
print green("Creating source package success!")
@task
def put_package(): #上传任务函数
print yellow("Start put package...")
with settings(warn_only=True):
with cd(env.deploy_project_root+env.deploy_release_dir):
run("mkdir %s" % (env.deploy_version)) #创建版本目录
env.deploy_full_path=env.deploy_project_root + env.deploy_release_dir + "/"+env.deploy_version
with settings(warn_only=True): #上传项目压缩包至此目录
result = put(env.project_tar_source + env.project_pack_name +".tar.gz", env.deploy_full_path)
if result.failed and no("put file failed, Continue[Y/N]?"):
abort("Aborting file put task!")
with cd(env.deploy_full_path): #成功解压后删除压缩包
run("tar -zxvf %s.tar.gz" % (env.project_pack_name))
run("rm -rf %s.tar.gz" % (env.project_pack_name))
print green("Put & untar package success!")
@task
def make_symlink(): #为当前版本目录做软链接
print yellow("update current symlink")
env.deploy_full_path=env.deploy_project_root + env.deploy_release_dir + "/"+env.deploy_version
with settings(warn_only=True): #删除软链接,重新创建并指定软链源目录,新版本生效
run("rm -rf %s" % (env.deploy_project_root + env.deploy_current_dir))
run("ln -s %s %s" % (env.deploy_full_path, env.deploy_project_root + env.deploy_current_dir))
#删除软链接,重新创建并指定软链源目录,新版本生效
print green("rollback success!")
@task
def go(): #自动化程序版本发布入口函数
tar_source()
put_package()
make_symlink()
嵌套函数
闭包closures
函数套函数
import time
def hl(func):
def wrap():
begin = int(time.time())
print begin
func()
end = int(time.time())
print end
print "cost:",end - begin
return end - begin
return wrap
def t():
time.sleep(1)
hl(t)()
装饰器
函数执行前扩展一些函数、执行后扩展一些函数
import time
def hl(func):
def wrap():
begin = int(time.time())
print begin
func()
end = int(time.time())
print end
print "cost:",end - begin
return end - begin
return wrap
@hl
def t():
time.sleep(1)
t()
##############################
def mb(func):
def wrap():
return '<b>' + func() + '</b>'
return wrap
def mi(func):
def wrap():
return '<i>' + func() + '</i>'
return wrap
@mb
@mi
def hello():
return('hello')
print(hello())
pip.conf
#$HOME/.pip/pip.conf
[global]
index-url = http://pypi.douban.com/simple
[install]
trusted-host = pypi.douban.com
或者
[global]
index-url = http://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host = mirrors.aliyun.com
windows设置HOME变量,放到%HOME%/pip/pip.ini
单次使用 pip install Jinja2 -i http://pypi.douban.com/simple
小技巧
交换变量
x = 6
y = 5
x, y = y, x
print x # 打印:5
print y # 打印:6
if 语句在行内
作用相当于 C/Java 的三目运算符
a = "Hello" if True else "World"
b = "Hello" if False else "World"
print a # 打印:Hello
print b # 打印:World
连接
# 列表、元组 拼接
nfc = ["Packers", "49ers"]
afc = ["Ravens", "Patriots"]
print nfc + afc # 打印:['Packers', '49ers', 'Ravens', 'Patriots']
# 字符串 拼接
print str(1) + " world" # 打印:1 world
# 数值的这种写法,我还不清楚是什么, 会当成字符串处理,却又不是真正的字符串
print `1` + " world" # 打印:1 world
# python2.x 的 print 可以这样打印多个不同类型的内容
print 1, "world" # 打印:1 world
print nfc, 1 # 打印:['Packers', '49ers'] 1
# python3.x 的 print 可以这样打印多个不同类型的内容(效果同上面 2.x 的)
print(1, "world", end=' ') # 打印:1 world
print(nfc, 1, end=' ') # 打印:['Packers', '49ers'] 1
序列(包括:列表、元组、字符串)
带索引的 序列 迭代(很实用的获取索引的写法)
teams = ["Packers", "49ers", "Ravens", "Patriots"]
for index, team in enumerate(teams):
print index, team # 打印如:0 Packers
序列 的乘法
items = [0]*3
print(items)
序列 拼接为字符串
teams = ["Packers", "49ers", "Ravens", "Patriots"]
print(", ".join(teams))
序列 的子集
teams = ["Packers", "49ers", "Ravens", "Patriots"]
print(teams[-2]) # 最后两项(负数表示倒数几项)
print(teams[:]) # 复制一份
print(teams[::-1]) # 反序
print(teams[::2]) # 奇数项
print(teams[1::2]) # 偶数项
数值比较
这是我见过诸多语言中很少有的如此棒的简便法
x = 2
if 3 > x > 1:
print x # 打印:2
if 1 < x > 0:
print x # 打印:2
同时迭代两个列表
nfc = ["Packers", "49ers"]
afc = ["Ravens", "Patriots"]
for teama, teamb in zip(nfc, afc):
print teama + " vs. " + teamb
# 打印1: Packers vs. Ravens
# 打印2: 49ers vs. Patriots
60个字符解决FizzBuzz
前段时间Jeff Atwood 推广了一个简单的编程练习叫FizzBuzz,问题引用如下:
写一个程序,打印数字1到100,3的倍数打印“Fizz”来替换这个数,5的倍数打印“Buzz”,对于既是3的倍数又是5的倍数的数字打印“FizzBuzz”。
这里就是一个简短的,有意思的方法解决这个问题:
for x in range(101):print"fizz"[x%3*4::]+"buzz"[x%5*4::]or x
False == True
比起实用技术来说这是一个很有趣的事,在python中, True 和 False 是全局变量(值允许改变),因此:
False = True
if False:
print "Hello"
else:
print "World"
# 打印: Hello
流量转换
import math
def convertBytes(bytes, lst=None):
if lst is None:
lst=['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB']
i = int(math.floor( # 舍弃小数点,取小
math.log(bytes, 1024) # 求对数(对数:若 a**b = N 则 b 叫做以 a 为底 N 的对数)
))
if i >= len(lst):
i = len(lst) - 1
return ('%.2f' + " " + lst[i]) % (bytes/math.pow(1024, i))