1. 程式人生 > >鐵樂學python_day28_模塊學習3

鐵樂學python_day28_模塊學習3

pyo 遇到 ltr 還需要 輸出格式 分享圖片 無法 popen sts

大部份內容摘自授課老師的博客http://www.cnblogs.com/Eva-J/

OS模塊復習一二

技術分享圖片

>>> import os
>>> os.getcwd()  # 獲取當前所在目錄
‘D:\\PortableSoft\\Python35‘

>>> os.chdir(‘d:\\PortableSoft‘)  # 改變工作目錄,相當於cd命令
>>> os.getcwd()
‘d:\\PortableSoft‘

>>> os.curdir  # 獲取‘.‘字符串,相當於當前目錄
‘.‘
>>>
os.pardir # 獲取‘..‘字符串,相當於上級(父目錄)目錄 ‘..‘ >>> import os >>> os.sep ‘\\‘ >>> os.linesep ‘\r\n‘ >>> os.pathsep ‘;‘ >>> os.name ‘nt‘ os.system(‘dir‘) # 直接就運行完命令了 print(os.popen(‘dir‘).read()) # 執行的輸出有返回值 驅動器 E 中的卷是 VM 卷的序列號是 4AE6-716D E:\Python\day28 的目錄 2018-04-25
17:21 <DIR> . 2018-04-25 17:21 <DIR> .. 2018-04-25 17:11 4 new.txt 2018-04-25 17:21 323 OS模塊.py 2 個文件 327 字節 2 個目錄 62,048,944,128 可用字節

技術分享圖片

print(os.path)  # <module ‘ntpath‘ from ‘D:\\PortableSoft\\Python35\\lib\\ntpath.py‘>
print(os.path.abspath(os.curdir)) # E:\Python\day28 print(os.path.split(‘E:\Python\day28‘)) # (‘E:\\Python‘, ‘day28‘) print(os.path.abspath(os.pardir)) # E:\Python print(os.path.dirname(‘E:\Python\day28‘)) # E:\Python print(os.path.basename(‘E:\Python\day28‘)) # day28 print(os.path.exists(‘E:\Python\day28‘)) # True print(os.path.exists(‘E:\Python\day29‘)) # False print(os.path.join(‘E:\Python‘, ‘day28‘, ‘OS模塊.py‘)) # E:\Python\day28\OS模塊.py print(os.path.getmtime(‘E:\Python\day28‘)) # 1524649925.9140468 獲取到的是時間戳,所以還需要轉格式化字符串的時間 res = os.path.getmtime(‘E:\Python\day28‘) print(time.strftime(‘%Y-%m-%d %X, time.gmtime(res))) # 2018-04-25 09:57:58
補充:os.walk
os.walk輸入一個路徑名稱,以yield的方式(其實是一個生成器)返回一個三元組 dirpath, dirnames, filenames

例子:打印輸出目錄樹

import os
def travelTree(currentPath, count):
    ‘‘‘
    以樹狀的方式遞歸顯示文件目錄
    :param currentPath: 要顯示的目錄路徑
    :param count: 要顯示的目錄層級
    :return: 沒有返回值,直接遞歸打印輸出格式化好的文件樹
    ‘‘‘
    # 判斷傳入進來的路徑存不存在,不存在直接返回None
    if not os.path.exists(currentPath):
        return
    # 判斷傳入進來的路徑是否為文件
    if os.path.isfile(currentPath):
        # 是文件則返回文件名
        fileName = os.path.basename(currentPath)
        # 打印輸出定義好的 層級制表符 拼接 樹狀符號 再加文件名
        print(\t * count + ‘├── ‘ + fileName)
    # 當路徑是一個目錄時
    elif os.path.isdir(currentPath):
        # 打印輸出定義好的 層級制表符 拼接 樹狀符號 再加目錄路徑
        print(\t * count + ‘├── ‘ + currentPath)
        # 將目錄以列表方式放入一個列表中
        pathList = os.listdir(currentPath)
        # for循環並且遞歸重復前面操作
        for eachPath in pathList:
            travelTree(currentPath + ‘/‘ + eachPath, count + 1)

什麽是模塊?

常見的場景:一個模塊就是一個包含了python定義和聲明的文件,文件名就是模塊名字加上.py的後綴。
但其實import加載的模塊分為四個通用類別: 
  1 使用python編寫的代碼(.py文件)
  2 已被編譯為共享庫或DLL的C或C++擴展
  3 包好一組模塊的包
  4 使用C編寫並鏈接到python解釋器的內置模塊

為何要使用模塊?

如果你退出python解釋器然後重新進入,那麽你之前定義的函數或者變量都將丟失,因此我們通常將程序寫到文件中以便永久保存下來,需要時就通過python test.py方式去執行,此時test.py被稱為腳本script。

隨著程序的發展,功能越來越多,為了方便管理,我們通常將程序分成一個個的文件,這樣做程序的結構更清晰,方便管理。這時我們不僅僅可以把這些文件當做腳本去執行,還可以把他們當做模塊來導入到其他的模塊中,實現了功能的重復利用。

模塊可以包含可執行的語句和函數的定義,這些語句的目的是初始化模塊,它們只在模塊名第一次遇到導入import語句時才執行(import語句是可以在程序中的任意位置使用的,且針對同一個模塊很import多次,為了防止你重復導入,python的優化手段是:第一次導入後就將模塊名加載到內存了,後續的import語句僅是對已經加載大內存中的模塊對象增加了一次引用,不會重新執行模塊內的語句)

我們可以從sys.modules中找到當前已經加載的模塊,sys.modules是一個字典,內部包含模塊名與模塊對象的映射,該字典決定了導入模塊時是否需要重新導入。

每個模塊都是一個獨立的名稱空間,定義在這個模塊中的函數,把這個模塊的名稱空間當做全局名稱空間,這樣我們在編寫自己的模塊時,就不用擔心我們定義在自己模塊中全局變量會在被導入時,與使用者的全局變量沖突。

總結:首次導入模塊時會做三件事:

1.為源文件(導入的module模塊)創建新的名稱空間,在當中定義的函數和方法若是使用到了global時訪問的就是這個名稱空間。
2.在新創建的命名空間中執行模塊中包含的代碼;

導入模塊時到底執行了什麽?
In fact function definitions are also ‘statements’ that are ‘executed’; the execution of a module-level function definition enters the function name in the module’s global symbol table.
事實上函數定義也是“被執行”的語句,模塊級別函數定義的執行將函數名放入模塊全局名稱空間表,用globals()可以查看。

3.創建名字用導入的module名來引用該命名空間
這個名字和變量名沒什麽區別,都是‘第一類的’,且使用導入的module名字的方式可以訪問該py文件中定義的名字,被導入的py內的.名字與文件中的名字來自兩個完全不同的地方。

為模塊起別名:

為模塊名起別名,相當於json=seq;pickle=seq

示範用法一:
有兩中sql模塊mysql和oracle,根據用戶的輸入,選擇不同的sql功能

#mysql.py
def sqlparse():
    print(‘from mysql sqlparse‘)
#oracle.py
def sqlparse():
    print(‘from oracle sqlparse‘)

#test.py
db_type=input(‘>>: ‘)
if db_type == ‘mysql‘:
    import mysql as db
elif db_type == ‘oracle‘:
    import oracle as db

db.sqlparse() 

示範用法二: 
為已經導入的模塊起別名的方式對編寫可擴展的代碼很有用,
假設有兩個模塊xmlreader.py和csvreader.py,
它們都定義了函數read_data(filename):用來從文件中讀取一些數據,但采用不同的輸入格式。
可以編寫代碼來選擇性地挑選讀取模塊,例如

if file_format == ‘xml‘:
     import xmlreader as reader
elif file_format == ‘csv‘:
     import csvreader as reader
data=reader.read_date(filename)

from ... import...
對比import my_module,會將源文件的名稱空間‘my_module‘帶到當前名稱空間中,使用時必須是my_module.名字的方式。
而from 語句相當於import,也會創建新的名稱空間,
但是from是將my_module中的名字直接導入到當前的名稱空間中,
在當前名稱空間中,直接使用名字就可以了。

例:from math import pi

這樣在當前位置直接使用pi就好了,執行時,仍然回math文件全局名稱空間尋找名字pi。
需要特別強調的一點是:python中的變量賦值不是一種存儲操作,而只是一種綁定關系。
from同樣支持as,起別名。

另外
from my_module import * 把my_module中所有不是以下劃線(_)開頭的名字都導入到當前位置,
大部分情況下我們的python程序不應該使用這種導入方式,
因為*你不知道你導入什麽名字,很有可能會覆蓋掉你之前已經定義的名字。
而且可讀性極其的差,在交互式環境中導入時沒有問題。

在my_module.py中新增一行
__all__=[‘money‘,‘read1‘] 
#這樣在另外一個文件中用from my_module import * 導入的是列表中規定的兩個名字。

模塊的加載與修改

考慮到性能的原因,每個模塊只被導入一次,放入字典sys.modules中,
如果你改變了模塊的內容,你必須重啟程序,python不支持重新加載或卸載之前導入的模塊,
有的同學可能會想到直接從sys.modules中刪除一個模塊不就可以卸載了嗎,
註意了,你刪了sys.modules中的模塊對象仍然可能被其他程序的組件所引用,因而不會被清除。
特別的對於我們引用了這個模塊中的一個類,用這個類產生了很多對象,因而這些對象都有關於這個模塊的引用。

如果只是你想交互測試的一個模塊,使用 importlib.reload(), 
e.g. import importlib; importlib.reload(modulename),這只能用於測試環境。

把模塊當做腳本執行 
我們可以通過模塊的全局變量__name__來查看模塊名:

當做腳本運行:
__name__ 等於‘__main__‘

當做模塊導入:
__name__= 模塊名

作用:用來控制.py文件在不同的應用場景下執行不同的邏輯
if __name__ == ‘__main__‘:

模塊搜索路徑
python解釋器在啟動時會自動加載一些模塊,可以使用sys.modules查看。

在第一次導入某個模塊時(比如my_module),
會先檢查該模塊是否已經被加載到內存中(當前執行文件的名稱空間對應的內存),如果有則直接引用;
如果沒有,解釋器則會查找同名的內建模塊,如果還沒有找到就從sys.path給出的目錄列表中依次尋找my_module.py文件。

所以總結模塊的查找順序是:內存中已經加載的模塊->內置模塊->sys.path路徑中包含的模塊.

sys.path的初始化的值來自於:
The directory containing the input script (or the current directory when no file is specified).
PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).
The installation-dependent default.

需要特別註意的是:我們自定義的模塊名不應該與系統內置模塊重名。雖然每次都說,但是仍然會有人不停的犯錯。 
在初始化後,python程序可以修改sys.path,路徑放到前面的優先於標準庫被加載。
1 >>> import sys
2 >>> sys.path.append(‘/a/b/c/d‘)
3 >>> sys.path.insert(0,‘/x/y/z‘) #排在前的目錄,優先被搜索

註意:搜索時按照sys.path中從左到右的順序查找,位於前的優先被查找,
sys.path中還可能包含.zip歸檔文件和.egg文件,python會把.zip歸檔文件當成一個目錄去處理。

至於.egg文件是由setuptools創建的包,這是按照第三方python庫和擴展時使用的一種常見格式,
.egg文件實際上只是添加了額外元數據(如版本號,依賴項等)的.zip文件。
需要強調的一點是:只能從.zip文件中導入.py,.pyc等文件。
使用C編寫的共享庫和擴展塊無法直接從.zip文件中加載(此時setuptools等打包系統有時能提供一種規避方法),
且從.zip中加載文件不會創建.pyc或者.pyo文件,因此一定要事先創建他們,來避免加載模塊是性能下降。

官網鏈接:https://docs.python.org/3/tutorial/modules.html#the-module-search-path
搜索路徑:
當一個命名為my_module的模塊被導入時,解釋器首先會從內建模塊中尋找該名字,找不到,則去sys.path中找該名字。

sys.path從以下位置初始化:

1)執行文件所在的當前目錄
2)PTYHONPATH(包含一系列目錄名,與shell變量PATH語法一樣)
3)依賴安裝時默認指定的

註意:在支持軟連接的文件系統中,執行腳本所在的目錄是在軟鏈接之後被計算的,
換句話說,包含軟鏈接的目錄不會被添加到模塊的搜索路徑中。

在初始化後,我們也可以在python程序中修改sys.path,執行文件所在的路徑默認是sys.path的第一個目錄,
在所有標準庫路徑的前面。這意味著,當前目錄是優先於標準庫目錄的,
需要強調的是:我們自定義的模塊名不要跟python標準庫的模塊名重復。

end
2018-4-27

鐵樂學python_day28_模塊學習3