Python 001
Life is short, you need Python -- Bruce Eckel
why
有趣、可鼓捣
解决问题快速、有效
思路广、快乐多~
省手指头
Python 是一门好语言
content
- 环境准备
- 包管理
- hello, python
- 基本语法
- 日常任务
- sexy part
- 心得体会
- what's next
environment
- 不要在 Windows 中使用 Python
- 先看这里:python.org(注意:不是 .com)
- 2 or 3,先从 2 开始吧,3 很快也要续上~
- 安装
包管理工具:brew / pacman / apt-get / yum ... 手动编译: ./configure --prefix= && make && make install Dear ops 已经替我们装好了:/home/q/python27/bin/python
- 如无必要,不要自己手动编译安装
- 如果安装出现错误,不要逃跑!
package management
- 标准库功能不全或不好用时需要安扩展
- 操作系统包管理器中一般都有常用扩展
- 手动安装:python setup.py install (注意:which)
- pip
操作系统包管理器安装 pip 命令行:get-pip.py (f^cking GFW) 手动安装:wget http://xxx/pip-a.b.c.tar.gz 然后 python setup.py install pip 安装扩展:pip install abc 安装时指定来源:pip install abc -i http://pypi.douban.com/simple
hello python
which python
export PATH=/home/q/python27/bin:$PATH
python -V
Python 2.7.6 (default, Dec 28 2013, 20:51:17)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> print 'hello, world'
hello, world
$ python -c "print 'hello, world'"
hello, world
pip install ipython
pip install bpython
Python 做日常不需要 IDEREPL + 编辑器 =『试代码』= 正确的打开方式
basic syntax -- getting help
>>> help(5) Help on int object: (etc etc) >>> dir(5) ['__abs__', '__add__', ...] >>> abs.__doc__ 'abs(number) -> number Return the absolute value of the argument.'
basic syntax -- data types
a_int = 1 a_float = 3.14159265358979323846 a_str = 'a' a_str, b_str = 'a', "b" # 单双引号有区别吗? a_bool = False a_list = [2, 1, 'x', True] a_tuple = (3, 5) b_tuple = (3, ) is_c_a_tuple = (3) # 我是注释:看看 c 是什么类型 t = type(is_c_a_tuple) ''' 我是多行注释 也可以当做文档字符串 同时也是多行字符串的表示,写 sql 用这个可以排版哦 比 java[script] 一坨加号爽多了 ''' print t a_set = {3, 1, 3, 2} a_dict = { 'a': 22, 4: 'bb', 'u': u'哦,差点忘了 unicode string' }
basic syntax -- flow control
rangelist = range(10) >>> print rangelist [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] for number in rangelist: # Check if number is one of # the numbers in the tuple. if number in (3, 4, 7, 9): break else: continue else: # The "else" clause is optional and is # executed only if the loop didn't "break". pass # Do nothing if rangelist[1] == 2: print "The second item (lists are 0-based) is 2" elif rangelist[1] == 3: print "The second item (lists are 0-based) is 3" else: print "Dunno" while rangelist[1] == 1: pass
basic syntax -- function
# Same as def funcvar(x): return x + 1 funcvar = lambda x: x + 1 >>> print funcvar(1) 2 # an_int and a_string are optional, they have default values # if one is not passed (2 and "A default string", respectively). def passing_example(a_list, an_int=2, a_string="A default string"): a_list.append("A new item") an_int = 4 return a_list, an_int, a_string >>> my_list = [1, 2, 3] >>> my_int = 10 >>> print passing_example(my_list, my_int) ([1, 2, 3, 'A new item'], 4, "A default string") >>> my_list [1, 2, 3, 'A new item'] >>> my_int 10
basic syntax -- exception
def some_function(): try: # Division by zero raises an exception 10 / 0 except ZeroDivisionError: print "Oops, invalid." else: # Exception didn't occur, we're good. pass finally: # This is executed after the code block is run # and all exceptions have been handled, even # if a new exception is raised while handling. print "We're done with that." >>> some_function() Oops, invalid. We're done with that.
basic syntax -- class
# We subclass from object to get a class. class Human(object): # A class attribute. It is shared by all instances of this class species = "H. sapiens" # Basic initializer def __init__(self, name): # Assign the argument to the instance's name attribute self.name = name # An instance method. All methods take "self" as the first argument def say(self, msg): return "%s: %s" % (self.name, msg) # A class method is shared among all instances # They are called with the calling class as the first argument @classmethod def get_species(cls): return cls.species # A static method is called without a class or instance reference @staticmethod def grunt(): return "*grunt*"
power
- 数据抓取
- ETL
- web UI、API
- 科学计算、统计、机器学习
- 系统运维
- 网络连接
- 安全
- 图像处理
- 数据库、cache、队列管理
- 各种开发、测试小工具
- 各种其他生态系统的 wrapper
daily routines -- begin
#!/usr/bin/env python
# coding=utf-8
import os
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
pwd = os.path.dirname(os.path.abspath(__file__)) + '/'
def main():
print 'hello python'
if __name__ == '__main__':
main()
daily routines -- postgres
import psycopg2
import psycopg2.extras
def get_hs():
con = psycopg2.connect(
database = 'hotel',
user = 'searcher',
password = '''abcdefg1234567''',
host = 'l-abc.def.com',
port = 5435
)
return con
def get_cursor(con):
return con.cursor(cursor_factory=psycopg2.extras.DictCursor)
con = get_hs()
cur = get_cursor(con)
try:
cur.execute('begin')
cur.execute('truncate table city_suggest_app_info')
insert_sql = 'insert into city_suggest_app_info(city_id, citytag, app, app_info) values (%s, %s, %s, %s)'
cur.executemany(insert_sql, rows)
cur.execute('commit')
except:
logger.error('something wrong')
cur.execute('rollback')
finally:
cur.close()
con.close()
daily routines -- mysql
import pymysql
def get_hotel_hive():
con = pymysql.connect(
host='l-abc.def.com',
port=3306,
user='hotel_hive',
passwd='xxx',
db='hotel_hive',
charset='utf8'
)
return con
con = get_hotel_hive()
cur = con.cursor(pymysql.cursors.DictCursor)
seq_score = {}
cur.execute("select seq, score from top_query_all where cityurl = 'chengdu' and server_tag = 'A' and query = '7天连锁' ")
for r in cur.fetchall():
seq = r['seq']
seq_score[seq] = r['score']
con.commit()
cur.close()
con.close()
daily routines -- http request
import requests
resp = requests.get('http://tuan.aaa.bbb.com/render/cityHotelCount.jsp')
jd = resp.json()
for city, count in jd['cities'].items():
info = t.get(city)
if not info:
continue
info['tuan']['weight'] = info['hs']['weight']
info['tuan']['online_count'] = count
daily routines -- json
In [71]: import json
In [72]: d = {'a': '你好', '世界': 'b'}
In [73]: print json.dumps(d)
{"a": "\u4f60\u597d", "\u4e16\u754c": "b"}
In [74]: print json.dumps(d, ensure_ascii=False, indent=2, sort_keys=True)
{
"a": "你好",
"世界": "b"
}
In [77]: s = '{"ping":"pong", "a":3, "中文":"2014-05-19"}'
In [78]: jd = json.loads(s)
In [79]: for k, v in jd.items():
....: print k, v, type(v)
....:
a 3 <type 'int'>
中文 2014-05-19 <type 'unicode'>
ping pong <type 'unicode'>
daily routines -- http server
python -m SimpleHTTPServer 8000
# 比较简单的文件传文件策略(网上可找到支持带上传的版本)
# pip install Flask
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
# $ python hello.py
# * Running on http://localhost:5000/
daily routines -- dev ops
from fabric.api import *
import datetime, time, re
env.user = 'gavin'
def h(h_str):
p = re.compile('\[(\d+)-(\d+)\]')
m = p.search(h_str)
a = int(m.group(1))
b = int(m.group(2))
env.hosts = [re.sub(p, str(i), h_str) for i in range(a, b + 1)]
def r(cmd):
run(cmd)
def s(cmd):
sudo(cmd)
daily routines -- dev ops
@parallel
scripts = ['export_ctrip_view.sh', 'export_detail_click.sh']
with cd('/home/q/tools/bin'):
for s in scripts:
sudo('rm %s' % s)
put('./%s' % s, s, use_sudo=True)
sudo('chown root:root %s' % s)
sudo('chmod a+x %s' % s)
@parallel
def add_group_and_user():
sudo('groupadd hadoop_hotel')
sudo('sudo useradd hadoop_hotel -g hadoop_hotel -M')
sudo('sudo usermod -p "your_password" hadoop_hotel')
fab -f fab.py h:h_str=l-pgstats[1-2].h.xxx r:cmd=uptime
daily routines -- dev ops
[inet_http_server] ; inet (TCP) server disabled by default
port=*:8091 ; (ip_address:port specifier, *:port for all iface)
username=gavin ; (default is no username (open server))
password=gavin ; (default is no password (open server))
[program:head_image_sync]
command = /home/work/python27/bin/python /home/work/app/head_image_sync/web.py
directory = /home/work/app/head_image_sync/
autostart = true
autorestart = true
stderr_logfile = /home/work/app/head_image_sync/logs/stderr.log
stdout_logfile = /home/work/app/head_image_sync/logs/stdout.log
supervisord -f xxx.conf
supervisorctl start/stop/restart your_app
supervisorctl update/reload
daily routines -- misc
def get_logger():
level = logging.DEBUG
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(module)s[%(lineno)d] - %(funcName)s - %(message)s')
logger = logging.getLogger(__name__)
logger.setLevel(level)
ch = logging.StreamHandler()
ch.setLevel(level)
ch.setFormatter(formatter)
logger.addHandler(ch)
return logger
logger = get_logger()
sexy part -- list comprehension
a = [1, 2, 3]
b = [ i**2 for i in a ]
print b
[1, 4, 9]
c = { str(i) : i / 2.5 for i in a }
print c
{'1': 0.4, '3': 1.2, '2': 0.8}
d = { i**2 for i in [-1, 0, 1] }
print d
set([0, 1])
sexy part -- functional
a = [1, 3, 5] b = map(str, a) print b ['1', '3', '5'] c = reduce(lambda x, y: x + y, a) print c 9 d = filter(lambda x: x > 2, a) print d [3, 5] # python lambda 表达式,是从 Lisp 借用来的,可以用在任何需要函数的地方
# 可以当做变量、参数
sexy part -- decorator
def memo(fn):
cache = {}
miss = object()
def wrapper(*args):
result = cache.get(args, miss)
if result is miss:
result = fn(*args)
cache[args] = result
return result
return wrapper
@memo
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
sexy part -- with statement
file = open("/tmp/foo.txt")
try:
data = file.read()
finally:
file.close()
# ==> 有了 with
with open('output.txt', 'w') as f:
f.write('Hi there!')
# 数据库、HTTP 连接之类的都可以,只要按 python 标准实现 context 管理
sexy part -- simplicity
# 一句话搞定一棵树
def tree():
return collections.defaultdict(tree)
t = tree()
t['public']['static']['void']['main'] = 'hello world'
print json.dumps(t, indent=2)
{
"public": {
"static": {
"void": {
"main": "hello world"
}
}
}
}
sexy part -- simplicity
it = itertools.product([1, 3], [2, 4])
it.next()
(1, 2)
it.next()
(1, 4)
it = itertools.combinations([3, 4, 5], 2)
it.next()
(3, 4)
it.next()
(3, 5)
it.next()
(4, 5)
sexy part -- zen
In [125]: import this The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those!
sexy part -- zen
优美胜于丑陋(Python 以编写优美的代码为目标) 明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似) 简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现) 复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁) 扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套) 间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题) 可读性很重要(优美的代码是可读的) 即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上) 不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码) 当存在多种可能,不要尝试去猜测 而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法) 虽然这并不容易,因为你不是 Python 之父(这里的 Dutch 是指 Guido ) 做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量) 如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准) 命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)
gotcha
- Python 多用于鼓捣、多数都是浅尝辄止,但是很有乐
- 有问题先 STFW & RTFM
- 官方文档、华蟒邮件列表、stackoverflow、reddit 多逛逛。其他 nodejs、ruby 社区也没事儿逛逛
- 亲身经历的烂坑争取深挖一下
- 发挥想象力,有很多好玩的东西
Questions ?
Thank you !
Python 001
By songchao
Python 001
人生苦短,快来一起鼓捣 Python ~
- 2,258