python高级编程

来源:互联网 发布:淘宝男士护肤 编辑:程序博客网 时间:2024/05/18 02:27

python并行编程

python可以多线程多进程编程,多线程可以共享全局变量,多进程不能。多线程中,所有子线程的进程号相同;多进程中,不同的子进程进程号不同。
多线程用thread/threading库,多进程用multiprocessing

多线程:

可以看解释http://www.cnblogs.com/tqsummer/archive/2011/01/25/1944771.html和官网:http://www.python.org/doc/2.5.2/lib/module-threading.html。
thread,有两种方法,1.函数式:调用thread模块中的start_new_thread()函数来产生新线程。2.创建threading.Thread的子类来包装一个线程对象

import osimport threaddef timer(no, interval):      cnt = 0      while cnt<10:          print 'Thread:(%d) Time:%s\n'%(no, time.ctime())          time.sleep(interval)          cnt+=1      thread.exit_thread() thread.start_new_thread(timer, (1,1))  #thread.start_new_thread(function, args[, kwargs])的第一个参数是线程函数(本例中的timer方法),第二个参数是传递给线程函数的参数,它必须是tuple类型thread.start_new_thread(timer, (2,2))import threading  import time  class timer(threading.Thread): #The timer class is derived from the class threading.Thread      def __init__(self, num, interval):          threading.Thread.__init__(self)          self.thread_num = num          self.interval = interval          self.thread_stop = False      def run(self): #Overwrite run() method, put what you want the thread do here          while not self.thread_stop:              print 'Thread Object(%d), Time:%s\n' %(self.thread_num, time.ctime())              time.sleep(self.interval)      def stop(self):          self.thread_stop = True thread1 = timer(1, 1)  thread2 = timer(2, 2)  thread1.start()  thread2.start()  time.sleep(10)  thread1.stop()  thread2.stop()

多线程同步问题:
1.锁:hreading.RLock类创建锁,线程可以使用锁的acquire()方法获得锁,这样锁就进入“locked”状态。每次只有一个线程可以获得锁。如果当另一个线程试图获得这个锁的时候,就会被系统变为“blocked”状态,直到那个拥有锁的线程调用锁的release()方法来释放锁,这样锁就会进入“unlocked”状态。“blocked”状态的线程就会收到一个通知,并有权利获得锁。如果多个线程处于“blocked”状态,所有线程都会先解除“blocked”状态,然后系统选择一个线程来获得锁,其他的线程继续沉默(“blocked”)
2.临界区设置条件变量Condition
首先一个线程成功获得一个条件变量后,调用此条件变量的wait()方法会导致这个线程释放这个锁,并进入“blocked”状态,直到另一个线程调用同一个条件变量的notify()方法来唤醒那个进入“blocked”状态的线程。如果调用这个条件变量的notifyAll()方法的话就会唤醒所有的在等待的线程。
锁和条件变量以及一个消费者、生产者例子参考http://www.cnblogs.com/tqsummer/archive/2011/01/25/1944771.html

多进程

当被操作对象数目不太大时,可以直接利用multiprocessing中的Process动态成生多个进程,当进程数目比较多时,使用pool,Pool可以提供指定数量的进程供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。
一个好的教程http://www.cnblogs.com/kaituorensheng/p/4445418.html
process创建进程
子进程设置了daemon属性,主进程结束,它们就随着结束了。
当多个进程需要访问共享资源的时候,Lock可以用来避免访问的冲突。
Semaphore用来控制对共享资源的访问数量,例如池的最大连接数。
Event用来实现进程间同步通信。
Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递。put方法用以插入数据到队列中,put方法还有两个可选参数:blocked和timeout。get方法可以从队列读取并且删除一个元素。
Pipe方法返回(conn1, conn2)代表一个管道的两个端。Pipe方法有duplex参数,如果duplex参数为True(默认值),那么这个管道是全双工模式,也就是说conn1和conn2均可收发。duplex为False,conn1只负责接受消息,conn2只负责发送消息。

import multiprocessingimport timedef worker_1(interval):    print "worker_1"    time.sleep(interval)    print "end worker_1"def worker_2(interval):    print "worker_2"    time.sleep(interval)    print "end worker_2"def worker_3(interval):    print "worker_3"    time.sleep(interval)    print "end worker_3"if __name__ == "__main__":    p1 = multiprocessing.Process(target = worker_1, args = (2,))    p2 = multiprocessing.Process(target = worker_2, args = (3,))    p3 = multiprocessing.Process(target = worker_3, args = (4,))    p1.start()    p2.start()    p3.start()    print("The number of CPU is:" + str(multiprocessing.cpu_count()))    for p in multiprocessing.active_children():        print("child   p.name:" + p.name + "\tp.id" + str(p.pid))    print "END!!!!!!!!!!!!!!!!!"

python网络编程

借鉴:http://blog.csdn.net/alpha5/article/details/24122749
1.建立socket

#分两步:建立socket对象,连接到远程服务器上import sockets = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  #指明通信类型和协议家族port = socket.getservbyname("http", "tcp")#通过协议名和端口名查找端口号s.connect(("www.baidu.com", port))print "Connected from", s.getsockname()  #获得本地机器的ip和端口号(端口号由操作系统随机分配,每次都不一样)print "Connected to", s.getpeername()    #获得连接机器的ip和端口号

这里写图片描述
一个简单的服务器:

写一个互联网服务器,我们使用的socket模块插座功能可用来创建一个socket对象。一个Socket对象,然后用来调用其他函数来设置套接字服务器.

现在调用bind(主机名,端口)函数,给定主机上的一个端口指定为您服务.

接下来,调用的accept方法返回的对象。这种方法等待,直到一个客户端连接到您指定的端口,然后返回一个连接对象,表示客户端的连接.

#!/usr/bin/python           # This is server.py fileimport socket               # Import socket modules = socket.socket()         # Create a socket objecthost = socket.gethostname() # Get local machine nameport = 12345                # Reserve a port for your service.s.bind((host, port))        # Bind to the ports.listen(5)                 # Now wait for client connection.while True:   c, addr = s.accept()     # Establish connection with client.   print 'Got connection from', addr   c.send('Thank you for connecting')   c.close()                # Close the connection

一个简单的客户端:

现在我们将编写一个非常简单的客户端程序,这将打开一个连接到一个特定的端口12345和给定的主机。这是非常简单的创建一个socket客户端使用Python的socket模块功能.

socket.connect(主机名或IP, 端口)打开到主机上的TCP端口的连接.

一旦你打开一个套接字,你可以看到它像任何IO对象。当完成后,记得要关闭它,你会关闭文件。
下面的代码是一个非常简单的客户端连接到一个特定的主机和端口,读取从套接字任何可用的数据,然后退出:

#!/usr/bin/python           # This is client.py fileimport socket               # Import socket modules = socket.socket()         # Create a socket objecthost = socket.gethostname() # Get local machine nameport = 12345                # Reserve a port for your service.s.connect((host, port))print s.recv(1024)s.close                     # Close the socket when done

python爬虫

http://www.xker.com/page/e2014/1108/142377.html
Scrapy是一个使用Python编写的,轻量级的,简单轻巧.使用步骤:

  • 新建项目 (Project):新建一个新的爬虫项目
  • 明确目标(Items):明确你想要抓取的目标
  • 制作爬虫(Spider):制作爬虫开始爬取网页
  • 存储内容(Pipeline):设计管道存储爬取内容

命令行:scrapy startproject tutorial会创建一个tutorial的文件夹,文件夹中:

  • scrapy.cfg:项目的配置文件
  • tutorial/:项目的Python模块,将会从这里引用代码-
  • tutorial/items.py:项目的items文件
  • tutorial/pipelines.py:项目的pipelines文件
  • tutorial/settings.py:项目的设置文件

在Scrapy中,items是用来加载抓取内容的容器,一般来说,item可以用scrapy.item.Item类来创建,并且用scrapy.item.Field对象来定义属性.
修改tutorial目录下的items.py文件,在原本的class后面添加我们自己的class:

class DmozItem(Item):      title = Field()      link = Field()      desc = Field() 

要建立一个Spider,你必须用scrapy.spider.BaseSpider创建一个子类,并确定三个强制的属性:
name:爬虫的识别名称,必须是唯一的,在不同的爬虫中你必须定义不同的名字。
start_urls:爬取的URL列表。爬虫从这里开始抓取数据,所以,第一次下载的数据将会从这些urls开始。其他子URL将会从这些起始URL中继承性生成。
parse():解析的方法,调用的时候传入从每一个URL传回的Response对象作为唯一参数,负责解析并匹配抓取的数据(解析为item),跟踪更多的URL。

下面我们来写第一只爬虫,命名为dmoz_spider.py,保存在tutorial\spiders目录下。

from scrapy.spider import Spider  class DmozSpider(Spider):      name = "dmoz"      allowed_domains = ["dmoz.org"]  #allow_domains是搜索的域名范围,也就是爬虫的约束区域,规定爬虫只爬取这个域名下的网页。    start_urls = [          "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",          "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"      ]      def parse(self, response):          filename = response.url.split("/")[-2]          open(filename, 'wb').write(response.body) 

在tutorial目录下打开命令窗口,输入:scrapy crawl dmoz
首先,Scrapy为爬虫的 start_urls属性中的每个URL创建了一个 scrapy.http.Request 对象 ,并将爬虫的parse 方法指定为回调函数。
然后,这些 Request被调度并执行,之后通过parse()方法返回scrapy.http.Response对象,并反馈给爬虫。
取爬虫内容时,用 XPath表达式,例如:

  • /html/head/title: 选择HTML文档元素下面的 标签。
  • /html/head/title/text(): 选择前面提到的 元素下面的文本内容
  • //td: 选择所有 元素
  • //div[@class=”mine”]: 选择所有包含 class=”mine” 属性的div 标签元素

为了方便使用XPaths,Scrapy提供XPathSelector 类,有两种可以选择,HtmlXPathSelector(HTML数据解析)和XmlXPathSelector(XML数据解析)。
必须通过一个 Response 对象对他们进行实例化操作。
你会发现Selector对象展示了文档的节点结构。因此,第一个实例化的selector必与根节点或者是整个目录有关 。

在Scrapy里面,Selectors 有四种基础的方法(点击查看API文档):

  • xpath():返回一系列的selectors,每一个select表示一个xpath参数表达式选择的节点
  • css():返回一系列的selectors,每一个select表示一个css参数表达式选择的节点
  • extract():返回一个unicode字符串,为选中的数据
  • re():返回一串一个unicode字符串,为使用正则表达式抓取出来的内容
    对上面的例子中parse函数中增加selector
   def parse(self, response):          sel = Selector(response)          sites = sel.xpath('//ul[@class="directory-url"]/li')          items = []          for site in sites:              item = DmozItem()              item['title'] = site.xpath('a/text()').extract()              item['link'] = site.xpath('a/@href').extract()              item['desc'] = site.xpath('text()').extract()              items.append(item)          return items   

存储内容
保存信息的最简单的方法是通过Feed exports,主要有四种:JSON,JSON lines,CSV,XML。
我们将结果用最常用的JSON导出,命令如下:-o 后面是导出文件名,-t 后面是导出类型。
scrapy crawl dmoz -o items.json -t json

重要函数

0.lambda
需要一个函数,但是又不想费神去命名一个函数的场合,匿名函数,匿名函数一般用在map,reduce,filter等等。
1.map
根据提供的函数对指定的序列做映射,定义为:map(function, sequence[,sequence,…])—>list

map(lambda x:x+2, [1, 2, 3]) #2,4,5map(lambda x,y:x+y, [1, 2], [1, 2])# [2,4]a=[{'type': 2, 'ID': 1}, {'type': 4, 'ID': 2}, {'ID': 3}]map(lambda x:x['ID'], a)#[1,2,3]map(lambda x:x['type'], a) #error,其中的一个键不存在({'ID':3}不存在typedef func1(x):   return x**2map(func1, [1, 2, 3]) #[1,4,9] 可以使用普通函数map(None, [1, 2, 3, 4], [1, 2, 3, 4,5], [1, 2, 3])#[(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, None), (None, 5, None)] 不指定函数,类似于zip函数,但是与zip函数不一样zip([1, 2, 3, 4], [1, 2, 3, 4,5], [1, 2, 3])#[(1, 1, 1), (2, 2, 2), (3, 3, 3)]

2.filter
对指定的序列进行过滤操作
filter(function or None, sequence) -> list, tuple, or string

filter(lambda x:x%2==1, [1, 2, 3]) #[1,3]

3.reduce
函数会对参数序列中元素进行累积,reduce(function, sequence[, initial]) -> value, function必须是有2个参数的函数

reduce(lambda x, y:x+y, [1,2,3,4])#10reduce(lambda x, y:x+y, [1,2,3,4], 10)#10是initial参数,((((10+1)+2)+3)+4)
0 0
原创粉丝点击