常用模块

文件操作##

读取文件

  try:
    f = open("test.txt", "r")
    print f.read()
  finally:
    if f: f.close()

可以使用with块缩短代码

  with open("test.txt", "r") as f:
    print f.read()

分块读取

  f.read(size) 

按行读取:如果要一次性读取所有行,只需调用readlines()

  f.readline()  #  按行读取, 如果要一次性读取所有行,只需调用readlines()
  open("test.txt", "rb")  #  读取二进制文件

读取非ASC2编码的文件:两种方式
第一种方式:用二进制读取之后再转码
第二种方式:用第三个参数指定编码

 open("test.txt", "r", "utf8")

写文件:跟读文件一样

对象序列化##

python的原版对象不能进行序列化,必须转成Dict才可以。
cPickle和pickle:cPickle支持中文,能用就用

  d = { "name": "opower", "age": 18 }
  print pickle.dump(d)
  with open("test.txt", "r") as f:
    pickle.dump(d, f)
  print pickle.load(f)  #  反序列化

JSON:pickle是针对python的,通用的方法是转成JSON格式

  #  序列化和反序列化跟pickle是一样的(就是函数名后面多了个s)
  #  关键在于json的dump提供一个转化函数的参数,可以把一般对象转成Dict后再序列化
  def student2dict(std):
    return {
        'name': std.name,
        'age': std.age,
        'score': std.score
    }
  print(json.dumps(s, default=student2dict))

  #  因为通常class的实例都有一个__dict__属性,它就是一个dict,
  #  用来存储实例变量。也有少数例外,比如定义了__slots__的class。
  print(json.dumps(s, default=lambda obj: obj.__dict__))

  #  反序列一样也可以
  def dict2student(d):
    return Student(d['name'], d['age'], d['score'])

  json_str = '{"age": 20, "score": 88, "name": "Bob"}'
  print(json.loads(json_str, object_hook=dict2student))

多进程##

Linux和Unix的系统,有自带的fork系统函数可以生成进程

  #  getpid:获取当前进程的ID
  #  getppid:获取父进程的ID
  import os

  print 'Process (%s) start...' % os.getpid()
  pid = os.fork()
  if pid==0:
    print 'I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid())
  else:
    print 'I (%s) just created a child process (%s).' % (os.getpid(), pid)

如果是window平台,需要用multiprocessing模块的Process类

  #  如果是window平台,需要用multiprocessing模块的Process类
  from multiprocessing import Process
  import os

  #  子进程要执行的代码
  def run_proc(name):
    print 'Run child process %s (%s)...' % (name, os.getpid())

  if __name__=='__main__':
    print 'Parent process %s.' % os.getpid()
    p = Process(target=run_proc, args=('test',))
    print 'Process will start.'
    p.start()
    p.join()
    print 'Process end.'
  • 可以看出Process接受两个参数,第一个是进程的入口函数;第二个是传入的参数
  • join()函数意味着当前进程会停下来,等待子进程执行结束之后再执行
  • Process实际上比fork好用,multiprocessing库封装了fork

进程池:可以从进程池批量管理进程池

from multiprocessing import Pool
import os

def printInfo(idx):
    print "Index is",idx,", pid is",os.getpid()

if __name__=='__main__':
    p = Pool()
    for i in range(5):
        p. apply_async(printInfo, args=(i,))
    p.close()
    p.join()

close - 表示进程池不再接受进程(我的理解是所有进程池的进程start,所以join函数得在close之后执行)

进程间通讯:Queue列队和Pipes通道,详细看例子吧

  from multiprocessing import Process, Queue
  import os, time, random

  # 写数据进程执行的代码:
  def write(q):
    for value in ['A', 'B', 'C']:
      print 'Put %s to queue...' % value
      q.put(value)
      time.sleep(random.random())

  # 读数据进程执行的代码:
  def read(q):
    while True:
      value = q.get(True)
      print 'Get %s from queue.' % value

  if __name__=='__main__':
    # 父进程创建Queue,并传给各个子进程:
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    # 启动子进程pw,写入:
    pw.start()
    # 启动子进程pr,读取:
    pr.start()
    # 等待pw结束:
    pw.join()
    # pr进程里是死循环,无法等待其结束,只能强行终止:
    pr.terminate()

多线程##

利用线程的高级模块,创建线程和进程一样很简单

import threading, time, random

def printInfo():
    for i in range(5):
        time.sleep(random.random() * 3)
        print "Hello",i

if __name__=='__main__':
    thd = threading.Thread(target=printInfo)
    thd.start()
    thd.join()
    print "Sub thread ended"

线程锁:多线程和多进程最大的不同在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响,而多线程中,所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。(选自廖雪峰python教程)

import threading, time, random

store = 20
lock = threading.Lock()

def sell(name):
    global store
    while store > 0:
        lock.acquire()  #  加锁
        store -= 1
        print "use by",name,"current:",store
        lock.release()  #  解锁

if __name__=='__main__':
    thdSell1 = threading.Thread(target=sell, args=("sell1",))
    thdSell2 = threading.Thread(target=sell, args=("sell2",))
    thdSell1.start()
    thdSell2.start()
    thdSell1.join()
    thdSell2.join()
    print "Application ended"
  • 可以尝试着把加锁/解锁代码注释掉,查看结果
  • 如果最后看到负数输出,考虑是因为什么原因,怎么检查原因,最后应该怎么解决

线程局部变量:每个线程有自己需要维护的一组局部变量,如果线程有多个函数,要使用某个局部变量只能依靠参数传递,为了防止函数参数表爆表,py提供了Threading.local

import threading

local_child = threading.local()
lock = threading.Lock()

def giveFruit(fruit):
    lock.acquire()
    local_child.fruit = fruit
    print getInfo()
    lock.release()

def getInfo():
    return local_child.fruit

if __name__=='__main__':
    thdSell1 = threading.Thread(target=giveFruit, args=("apple",))
    thdSell2 = threading.Thread(target=giveFruit, args=("orange",))
    thdSell1.start()
    thdSell2.start()
    thdSell1.join()
    thdSell2.join()
    print "Application ended"

python属于语法相对简单的脚本语言,比起C等传统高级语言,优势在于开发迅捷。因此适用于性能要求不太高的场合,而这样的场合经常出现在普通IO操作上,因此,网络应用、大数据量的输入输入很适合py。但对计算效率要求高的应用(解码、加压解压、跑算法等),如果效果不佳,还是尝试用传统高级语言。

上面线程锁最后输出负数的例子,可以尝试在循环头部打印一下当前执行的线程是哪个

  ...
  while store > 0:
        print "This is",name
        lock.acquire()  #  加锁
  ...

我们会看下输出结果是:
This is sell1
use by sell2 current: 8
This is sell2
use by sell2 current: 7
This is sell2
use by sell2 current: 6
This is sell2
use by sell2 current: 5
This is sell2
use by sell2 current: 4
This is sell2
use by sell2 current: 3
This is sell2
use by sell2 current: 2
This is sell2
use by sell2 current: 1
This is sell2
use by sell1 current: 0
use by sell2 current: -1
可以看到,当库存还有9的时候,线程1进入循环,但紧接着被线程2打断。线程2一直执行到库存还有1的时候,也是进入循环之后被线程1打断,线程1用掉最后一个库存,但不要忘了,这个时候2已经进入循环了,于是它在0库存的基础上用了不存在的值。
修正的方法也很简单,做一个死循环,所有的逻辑都放在里面并被锁包住,跳出条件是库存小于等于0,便可以了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容