Python基礎之(十)模塊

編寫模塊

模塊是程序

模塊就是一個擴展名爲.py的Python程序。html

編寫模塊

#!/usr/bin/env python
# coding=utf-8

lang = "python"

引入模塊

>>> import sys
>>> sys.path.append("~/Documents/VBS/StartLearningPython/2code/pm.py")
>>> import pm
>>> pm.lang
'python'

當Python解釋器讀取了.py文件,先將它變成由字節碼組成的.pyc文件,而後這個.pyc文件交給一個叫作Python虛擬機的東西去運行(那些號稱編譯型的語言也是這個流程,不一樣的是它們先有一個明顯的編譯過程,編譯好了以後再運行)。若是.py文件修改了,Python解釋器會從新編譯,只是這個編譯過程不是徹底顯示給你看的。python

我這裏說的比較籠統,要深刻了解Python程序的執行過程,能夠閱讀這篇文章:說說Python程序的執行過程ios

有了.pyc文件後,每次運行就不須要從新讓解釋器來編譯.py文件了,除非.py文件修改了。這樣,Python運行的就是那個編譯好了的.pyc文件。git

if name == "__main__"

若是要做爲程序執行,則__name__ == "__main__";若是做爲模塊引入,則pm.__name__ == "pm",即屬性__name__的值是模塊名稱。程序員

模塊的位置

>>> import sys
>>> import pprint
>>> pprint.pprint(sys.path)  #查看全部模塊的位置

__all__在模塊中的做用

# /usr/bin/env python
    # coding:utf-8

    __all__ = ['_private_variable', 'public_teacher']

    public_variable = "Hello, I am a public variable."
    _private_variable = "Hi, I am a private variable."

    def public_teacher():
        print "I am a public teacher, I am from JP."    #Python 3: print("I am a public teacher, I am from JP.")

    def _private_teacher():
        print "I am a private teacher, I am from CN."    #Python 3:  print("I am a private teacher, I am from CN.")

__all__屬性以及相應的值,在__all__屬性列表中包含了一個私有變量的名字和一個函數的名字。這是在告訴引用本模塊的解釋器,這兩個東西是有權限被訪問的,並且只有這兩個東西。github

包或者庫

包或者庫,應該是比「模塊」大的。也的確如此,通常來說,一個「包」裏面會有多個模塊,固然,「庫」是一個更大的概念了,好比Python標準庫中的每一個庫都有好多個包,每一個包都有若干個模塊。web

一個包是由多個模塊組成,即多個.py的文件,那麼這個所謂「包」也就是咱們熟悉的一個目錄罷了。如今就須要解決如何引用某個目錄中的模塊問題了。解決方法就是在該目錄中放一個__init__.py文件。__init__.py是一個空文件,將它放在某個目錄中,就能夠將該目錄中的其它.py文件做爲模塊被引用。shell

自帶電池

在Python被安裝的時候,就有很多模塊也隨着安裝到本地的計算機上了。這些東西就如同「能源」、「電力」同樣,讓Python擁有了無限生機,可以很是垂手可得地無償使用不少模塊。因此,稱之爲「自帶電池」。json

那些在安裝Python時就默認已經安裝好的模塊被統稱爲「標準庫」。api

引用的方式

import pprint #引入模塊

from pprint import pprint #引入該模塊下的方法

from pprint import * #引入該模塊下的全部方法

import pprint as pr #重命名模塊

from pprint import pprint as pt  #重命名方法

深刻探究

  • dir(),查看對象的屬性和方法

  • help()查看對象的含義

幫助、文檔和源碼

print pprint.__doc__  #查看文檔
print pprint.__file__ #查看模塊的位置,根據這個位置查到源代碼

標準庫

sys

sys.argv

sys.argv是專門用來向python解釋器傳遞參數,名曰「命令行參數」。

$ python --version # --veriosn就是命令行參數
    Python 2.7.6

sys.exit()

退出當前程序.

在大多數函數中會用到return,其含義是終止當前的函數,並向調用函數的位置返回相應值(若是沒有就是None)。可是sys.exit()的含義是退出當前程序——不只僅是函數,併發起SystemExit異常。這就是二者的區別了。

若是使用sys.exit(0)表示正常退出。若須要在退出的時候有一個對人友好的提示,能夠用sys.exit("I wet out at here."),那麼字符串信息就被打印出來。

sys.stdout

與Python中的函數功能對照,sys.stdin得到輸入(等價於Python 2中的raw_input(),Python 3中的input()),sys.stdout負責輸出。

>>> f = open("stdout.md", "w")
    >>> sys.stdout = f  #重定向到文件
    >>> print "Learn Python: From Beginner to Master"        #Python 3: print("Learn Python: From Beginner to Master")
    >>> f.close()

copy

import copy
copy.copy() #淺拷貝
copy.deepcopy() #深拷貝

os

操做文件

import os
os.rename("22201.py", "newtemp.py") #重命名文件
os.remove("123.txt") #刪除一個文件,不能是目錄

操做目錄

os.listdir:顯示目錄中的內容(包括文件和子目錄)
os.getcwd:獲取當前工做目錄;
os.pardir:得到上一級目錄
os.chdir:改變當前工做目錄
os.makedirs, os.removedirs:建立和刪除目錄

文件和目錄屬性

os.stat(p)顯示文件或目錄的屬性
os.chmod()改變權限

操做命令

os模塊中提供了這樣的方法,許可程序員在Python程序中使用操做系統的命令。

>>> p
    '/home/qw/Documents/VBS/StarterLearningPython'
    >>> command = "ls " + p #命令複製給Command變量
    >>> command
    >>> os.system(command) #執行命令

須要注意的是,os.system()是在當前進程中執行命令,直到它執行結束。若是須要一個新的進程,可使用os.exec或者os.execvp。對此有興趣詳細瞭解的讀者,能夠查看幫助文檔瞭解。另外,os.system()是經過shell執行命令,執行結束後將控制權返回到原來的進程,可是os.exec()及相關的函數,則在執行後不將控制權返回到原繼承,從而使Python失去控制。

#!/usr/bin/env python
# coding=utf-8

import webbrowser
webbrowser.open("http://www.baidu.com") #跨平臺打開瀏覽器

heapq:堆

headpq模塊

>>> import heapq
    >>> heapq.__all__
    ['heappush', 'heappop', 'heapify', 'heapreplace', 'merge', 'nlargest', 'nsmallest', 'heappushpop']

heappush(heap, x):將x壓入堆heap

>>> import heapq
    >>> heap = []    
    >>> heapq.heappush(heap, 3)
    >>> heapq.heappush(heap, 9)
    >>> heapq.heappush(heap, 2)
    >>> heapq.heappush(heap, 4)
    >>> heapq.heappush(heap, 0)
    >>> heapq.heappush(heap, 8)
    >>> heap
    [0, 2, 3, 9, 4, 8]

heappop(heap):刪除最小元素

>>> heapq.heappop(heap)
    0
    >>> heap
    [2, 4, 3, 9, 8]

heapify():將列表轉換爲堆

>>> hl = [2, 4, 6, 8, 9, 0, 1, 5, 3]
    >>> heapq.heapify(hl)
    >>> hl
    [0, 3, 1, 4, 9, 6, 2, 5, 8]

heapreplace()heappop()heappush()的聯合,也就是刪除一個,同時加入一個

>>> heap
    [2, 4, 3, 9, 8]
    >>> heapq.heapreplace(heap, 3.14)
    2
    >>> heap
    [3, 4, 3.14, 9, 8]

deque:雙端隊列

>>> qlst.append(5)        #從右邊增長
>>> qlst
deque([1, 2, 3, 4, 5])
>>> qlst.appendleft(7)    #從左邊增長
>>> qlst
deque([7, 1, 2, 3, 4, 5])
    
>>> qlst.pop() #右邊刪除一個元素
5
>>> qlst
deque([7, 1, 2, 3, 4])
>>> qlst.popleft() # 左邊刪除一個元素
7
>>> qlst
deque([1, 2, 3, 4])
    
>>> qlst.rotate(3) #循環移動n個位置
>>> qlst
deque([2, 3, 4, 1])

calendar:日曆

import calendar
cal = calendar.month(2016,8)
print cal

    August 2016
Mo Tu We Th Fr Sa Su
 1  2  3  4  5  6  7
 8  9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

calendar(year,w=2,l=1,c=6)
返回year年的年曆,3個月一行,間隔距離爲c。 每日寬度間隔爲w字符。每行長度爲21* w+18+2* c。l是每星期行數。

isleap(year)判斷是否爲閏年,是則返回true,不然false.

leapdays(y1, y2)返回在y1,y2兩年之間的閏年總數,包括y1,但不包括y2.

month(year, month, w=2, l=1)返回year年month月日曆,兩行標題,一週一行。每日寬度間隔爲w字符。每行的長度爲7* w+6,l是每星期的行數。

monthcalendar(year,month)返回一個列表,列表內的元素仍是列表。每一個子列表表明一個星期,都是從星期一到星期日,若是沒有本月的日期,則爲0。

monthrange(year, month)返回一個元組,裏面有兩個整數。第一個整數表明着該月的第一天從星期幾是(從0開始,依次爲星期1、星期二,直到6表明星期日)。第二個整數是該月一共多少天。

weekday(year,month,day)輸入年月日,知道該日是星期幾(注意,返回值依然按照從0到6依次對應星期一到星期六)。

time

經常使用方法

time()得到的是當前時間(嚴格說是時間戳),只不過這個時間對人不友好,它是以1970年1月1日0時0分0秒爲計時起點,到當前的時間長度(不考慮閏秒)。

localtime()獲得的結果能夠稱之爲時間元組(也有括號),其各項的含義是:

索引 屬性 含義
0 tm_year
1 tm_mon
2 tm_mday
3 tm_hour
4 tm_min
5 tm_sec
6 tm_wday 一週中的第幾天
7 tm_yday 一年中的第幾天
8 tm_isdst 夏令時

gmtime()localtime()獲得的是本地時間,若是要國際化,就最好使用格林威治時間。

asctime()

>>> time.asctime()
    'Mon May  4 21:46:13 2015'
    
    time.asctime(h) #參數必須是時間元組,即localtime返回的值

ctime()

>>> time.ctime()
'Mon May  4 21:52:22 2015'
    
 >>> time.ctime(1000000)  #參數是時間戳
'Mon Jan 12 21:46:40 1970'

mktime()mktime()也是以時間元組爲參數,可是它返回的是時間戳

strftime()將時間元組按照指定格式要求轉化爲字符串。若是不指定時間元組,就默認爲localtime()值。

格式 含義 取值範圍(格式)
%y 去掉世紀的年份 00-99,如"15"
%Y 完整的年份 如"2015"
%j 指定日期是一年中的第幾天 001-366
%m 返回月份 01-12
%b 本地簡化月份的名稱 簡寫英文月份
%B 本地完整月份的名稱 完整英文月份
%d 該月的第幾日 如5月1日返回"01"
%H 該日的第幾時(24小時制) 00-23
%l 該日的第幾時(12小時制) 01-12
%M 分鐘 00-59
%S 00-59
%U 在該年中的第多少星期(以週日爲一週起點) 00-53
%W 同上,只不過是以週一爲起點 00-53
%w 一星期中的第幾天 0-6
%Z 時區 在中國大陸測試,返回CST,即China Standard Time
%x 日期 日/月/年
%X 時間 時:分:秒
%c 詳細日期時間 日/月/年 時:分:秒
%% ‘%’字符 ‘%’字符
%p 上下午 AM or PM

strptime()做用是將字符串轉化爲時間元組,其參數要指定兩個,一個是時間字符串,另一個是時間字符串所對應的格式,格式符號用上表中的。

>>> today = time.strftime("%y/%m/%d")
    >>> today
    '15/05/05'
    >>> time.strptime(today, "%y/%m/%d")
    time.struct_time(tm_year=2015, tm_mon=5, tm_mday=5, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=1, tm_yday=125, tm_isdst=-1)

datetime

datetime模塊中有幾個類:

  • datetime.date:日期類,經常使用的屬性有year/month/day

  • datetime.time:時間類,經常使用的有hour/minute/second/microsecond

  • datetime.datetime:日期時間類

  • datetime.timedelta:時間間隔,即兩個時間點之間的時間長度

  • datetime.tzinfo:時區類

date類

# 生成日期對象
>>> import datetime
>>> today = datetime.date.today()
>>> today
datetime.date(2015, 5, 5)

# 操做日期對象

>>> print today        #Python 3: print(today)
2015-05-05
>>> print today.ctime()        #Python 3: print(today.ctime())
Tue May  5 00:00:00 2015
>>> print today.timetuple()        #Python 3: print(today.timetuple())
time.struct_time(tm_year=2015, tm_mon=5, tm_mday=5, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=1, tm_yday=125, tm_isdst=-1)
>>> print today.toordinal()        #Python 3: print(today.toordinal())
735723
    
>>> print today.year
2015
>>> print today.month
5
>>> print today.day
5
    
# 時間戳與格式化時間格式的轉換

>>> to = today.toordinal()
>>> to
735723
>>> print datetime.date.fromordinal(to)
2015-05-05

>>> import time
>>> t = time.time()
>>> t
1430787994.80093
>>> print datetime.date.fromtimestamp(t)
2015-05-05

# 修改日期。

>>> d1 = datetime.date(2015,5,1)
>>> print d1
2015-05-01
>>> d2 = d1.replace(year=2005, day=5)
>>> print d2
2005-05-05

time類

# 生成time對象

>>> t = datetime.time(1,2,3)
>>> print t
01:02:03

# 經常使用屬性:

>>> print t.hour
1
>>> print t.minute
2
>>> print t.second
3
>>> t.microsecond
0
>>> print t.tzinfo
None

timedelta類

主要用來作時間的運算。

>>> now = datetime.datetime.now()
    >>> print now        #Python 3: print(now)
    2015-05-05 09:22:43.142520

# 對`now`增長5個小時;

    >>> b = now + datetime.timedelta(hours=5)
    >>> print b        #Python 3: print(b)
    2015-05-05 14:22:43.142520

# 增長兩週;

    >>> c = now + datetime.timedelta(weeks=2)
    >>> print c        #Python 3: print(c)
    2015-05-19 09:22:43.142520

# 計算時間差:

    >>> d = c - b
    >>> print d        #Python 3: print(d)
    13 days, 19:00:00

urllib

urllib模塊用於讀取來自網上(服務器上)的數據,好比很多人用Python作爬蟲程序,就可使用這個模塊。

# 在Python 2中,這樣操做:
    >>> import urllib
    >>> itdiffer =  urllib.urlopen("http://www.itdiffer.com")

# 可是若是讀者使用的是Python 3,必須換個姿式:

    >>> import urllib.request
    >>> itdiffer = urllib.request.urlopen("http://www.itdiffer.com")
    
    >>> print itdiffer.read() #獲得網頁的內容

urlopen()

urlopen()主要用於打開url文件,而後就得到指定url的數據,而後就如同在操做文件那樣來操做,獲得的對象叫作類文件對象。

參數說明一下:

  • url:遠程數據的路徑,經常是網址

  • data:若是使用post方式,這裏就是所提交的數據

  • proxies:設置代理

url編碼、解碼

url對其中的字符有嚴格的編碼要求,要對url進行編碼和解碼。

  • quote(string[, safe]):對字符串進行編碼。參數safe指定了不須要編碼的字符

  • urllib.unquote(string) :對字符串進行解碼

  • quote_plus(string [ , safe ] ) :與urllib.quote相似,但這個方法用'+'來替換空格' ',而quote用'%20'來代替空格

  • unquote_plus(string ) :對字符串進行解碼;

  • urllib.urlencode(query[, doseq]):將dict或者包含兩個元素的元組列表轉換成url參數。例如{'name': 'laoqi', 'age': 40}將被轉換爲"name=laoqi&age=40"

  • pathname2url(path):將本地路徑轉換成url路徑

  • url2pathname(path):將url路徑轉換成本地路徑

urlretrieve()

將遠程文件保存在本地存儲器中.

urllib.urlretrieve(url[, filename[, reporthook[, data]]])

  • url:文件所在的網址

  • filename:可選。將文件保存到本地的文件名,若是不指定,urllib會生成一個臨時文件來保存

  • reporthook:可選。是回調函數,當連接服務器和相應數據傳輸完畢時觸發本函數

  • data:可選。若是用post方式所發出的數據

函數執行完畢,返回的結果是一個元組(filename, headers),filename是保存到本地的文件名,headers是服務器響應頭信息。

urllib2

僅僅是針對Python 2的,在Python 3中,已經沒有urllib2這個模塊了,取代它的是urllib.request

Request類

>>>req = urllib2.Request("http://www.itdiffer.com")

# Python2
    >>> response = urllib2.urlopen(req)
    >>> page = response.read()
    >>> print page

Python 3:

    >>> response = urllib.request.urlopen(req)
    >>> page = response.read()
    >>> print(page)

urllib2或者urllib.request的東西還不少,好比還能夠:

  • 設置HTTP Proxy

  • 設置Timeout值

  • 自動redirect

  • 處理cookie

XML

Python提供了多種模塊來處理XML。

  • xml.dom.* 模塊:Document Object Model。適合用於處理 DOM API。它可以將XML數據在內存中解析成一個樹,而後經過對樹的操做來操做XML。可是,這種方式因爲將XML數據映射到內存中的樹,致使比較慢,且消耗更多內存。

  • xml.sax.* 模塊:simple API for XML。因爲SAX以流式讀取XML文件,從而速度較快,切少佔用內存,可是操做上稍複雜,須要用戶實現回調函數。

  • xml.parser.expat:是一個直接的,低級一點的基於 C 的 expat 的語法分析器。 expat接口基於事件反饋,有點像 SAX 但又不太像,由於它的接口並非徹底規範於 expat 庫的。

  • xml.etree.ElementTree (如下簡稱 ET):元素樹。它提供了輕量級的Python式的API,相對於DOM,ET快了不少
    ,並且有不少使人愉悅的API可使用;相對於SAX,ET也有ET.iterparse提供了 「在空中」 的處理方式,沒有必要加載整個文檔到內存,節省內存。ET的性能的平均值和SAX差很少,可是API的效率更高一點並且使用起來很方便。

ElementTree在標準庫中有兩種實現。一種是純Python實現:xml.etree.ElementTree ,另一種是速度快一點:xml.etree.cElementTree

若是使用的是Python 2,能夠像這樣引入模塊:

try:
        import xml.etree.cElementTree as ET
    except ImportError:
        import xml.etree.ElementTree as ET

若是是Python 3以上,就沒有這個必要了,只須要一句話import xml.etree.ElementTree as ET便可,而後由模塊自動來尋找適合的方式。顯然Python 3相對Python 2有了很大進步。

經常使用屬性和方法總結

ET裏面的屬性和方法很多,這裏列出經常使用的,供使用中備查。

Element對象

經常使用屬性:

  • tag:string,元素數據種類

  • text:string,元素的內容

  • attrib:dictionary,元素的屬性字典

  • tail:string,元素的尾形

針對屬性的操做

  • clear():清空元素的後代、屬性、text和tail也設置爲None

  • get(key, default=None):獲取key對應的屬性值,如該屬性不存在則返回default值

  • items():根據屬性字典返回一個列表,列表元素爲(key, value)

  • keys():返回包含全部元素屬性鍵的列表

  • set(key, value):設置新的屬性鍵與值

針對後代的操做

  • append(subelement):添加直系子元素

  • extend(subelements):增長一串元素對象做爲子元素

  • find(match):尋找第一個匹配子元素,匹配對象能夠爲tag或path

  • findall(match):尋找全部匹配子元素,匹配對象能夠爲tag或path

  • findtext(match):尋找第一個匹配子元素,返回其text值。匹配對象能夠爲tag或path

  • insert(index, element):在指定位置插入子元素

  • iter(tag=None):生成遍歷當前元素全部後代或者給定tag的後代的迭代器

  • iterfind(match):根據tag或path查找全部的後代

  • itertext():遍歷全部後代並返回text值

  • remove(subelement):刪除子元素

ElementTree對象

  • find(match)

  • findall(match)

  • findtext(match, default=None)

  • getroot():獲取根節點.

  • iter(tag=None)

  • iterfind(match)

  • parse(source, parser=None):裝載xml對象,source能夠爲文件名或文件類型對象.

  • write(file, encoding="us-ascii", xml_declaration=None, default_namespace=None,method="xml") 

實例

<?xml version="1.0" encoding="UTF-8"?>
<bookstore liu="a">
    <book category="COOKING">
        <title lang="en">Everyday Italian</title>
        <author>Giada De Laurentiis</author>
        <year>2005</year>
        <price>30.00</price>
    </book>
    <book category="CHILDREN">
        <title lang="en">Harry Potter</title>
        <author>J K. Rowling</author>
        <year>2005</year>
        <price>29.99</price>
    </book>
    <book category="WEB">
        <title lang="en">Learning XML</title>
        <author>Erik T. Ray</author>
        <year>2003</year>
        <price>39.95</price>
    </book>
</bookstore>
#!/usr/bin/env python
# coding=utf-8

import xml.etree.ElementTree as ET

fd = open("xml.xml")

data = fd.read()

tree = ET.ElementTree(file="xml.xml")
print tree

#得到根元素
root = tree.getroot()
print root.tag
print root.attrib

#得到根元素下面的元素
for child in root:
    print child.tag,child.attrib
    for gen in child:
        print gen.tag,gen.text

JSON

JSON建構於兩種結構:

  • 「名稱/值」對的集合(A collection of name/value pairs)。不一樣的語言中,它被理解爲對象(object),紀錄(record),結構(struct),字典(dictionary),哈希表(hash table),有鍵列表(keyed list),或者關聯數組 (associative array)。

  • 值的有序列表(An ordered list of values)。在大部分語言中,它被理解爲數組(array)。

python標準庫中有JSON模塊,主要是執行序列化和反序列化功能:

  • 序列化:encoding,把一個Python對象編碼轉化成JSON字符串

  • 反序列化:decoding,把JSON格式字符串解碼轉換爲Python數據對象

encoding: dumps()

data_json = json.dumps(data)
json.dumps(data, sort_keys=True, indent=2) #格式化輸出json數據

decoding: loads()

大json字符串

若是數據不是很大,上面的操做足夠了。但如今是所謂「大數據」時代了,隨便一個什麼業務都在說本身是大數據,顯然不能總讓JSON很小,事實上真正的大數據,再「大」的JSON也不行了。前面的操做方法是將數據都讀入內存,若是數據太大了就會內存溢出。怎麼辦?JSON提供了load()dump()函數解決這個問題,注意,跟上面已經用過的函數相比,是不一樣的,請仔細觀察。

>>> import tempfile    #臨時文件模塊
    >>> data
    [{'lang': ('python', 'english'), 'age': 40, 'name': 'qiwsir'}]
    >>> f = tempfile.NamedTemporaryFile(mode='w+')
    >>> json.dump(data, f)
    >>> f.flush()
    >>> print open(f.name, "r").read()        #Python 3: print(open(f.name, "r").read())
    [{"lang": ["python", "english"], "age": 40, "name": "qiwsir"}]

實例

{"code":20,"data":"liuguoquan","person":[{"name":"zhang","age":19,"sex":"male"},{"name":"zhang","age":20,"sex":"male"}]}
#!/usr/bin/env python
# coding=utf-8

import json

class B(object):
    def __init__(self):
        self.age = 0
        self.name = ""
        self.sex = ""

class A(object):  
    def __init__(self):
        self.code = 2
        self.data = ""
        self.person = []
    

f = open("sample.json")
value = f.read();
print value

ret = json.loads(value)
print type(ret)

a = A()
#對象轉爲字典
a.__dict__ = ret
print a.code
print a.data
print a.person
print type(a.person)

for item in a.person:
    b = B()
    b.__dict__ = item;
    print b.age
    print b.name
    print b.sex

第三方庫

安裝第三方庫

利用源碼安裝

在github.com網站能夠下載第三方庫的源碼,一般會看見一個 setup.py 的文件。

python setup.py install

pip管理工具

pip是一個以Python計算機程序語言寫成的軟件包管理系統,它能夠安裝和管理軟件包,另外很多的軟件包也能夠在「Python軟件包索引」(英語:Python Package Index,簡稱PyPI)中找到。

pip install XXXXXX(XXXXXX表明第三方庫的名字)便可安裝第三方庫。

相關文章
相關標籤/搜索