1. 程式人生 > >python之模塊、包的導入過程和開發規範

python之模塊、包的導入過程和開發規範

而是 port code 導入模塊 聲明 for 命名 bubuko 根據

摘要:導入模塊、導入包、編程規範


以My_module為例,My_module的代碼如下:
 __all__ = [name,read]

print(in mymodule)

name = 帥鍋

def read():
    print(in read,name)

def read2():
    print(in read2,name)

if __name__ == __main__:
    print(in mymodule)
    print(__name__ : ,__name__)


一、導入模塊
1、import 模塊名 1-1、在import的過程中發生了哪些事情: import一個模塊相當於先執行了一次這個被導入模塊,然後在本命名空間建立一個與被導入模塊命名空間的聯系, 相當於在本命名空間新建了一個變量,這個變量名稱是被導入模塊的名稱,指向被導入模塊的命名空間。 1-2、一個模塊不會被重復導入,也就是說,import了一次這個模塊,然後再import一次,也只是執行了第一次的imoptr import My_module # 執行了 import My_module # 不會執行 1-3、如何去使用被導入模塊中的名字 import My_module
print(My_module.name) # 打印出My_module中的name My_module.My_module_fun() # 執行了My_module中的函數 1-4、小結導入模塊的過程 導入模塊的時候: 1.尋找模塊 2.如果找到了,就開辟一塊空間,執行這個模塊 3.把這個模塊中用到的名字都收錄到新開辟的空間中 4.創建一個變量來引用這個模塊的空間(變量名與這個模塊名一致) *1.模塊不會被重復導入 *2.模塊和文件之間的內存空間始終是隔離的 *3.模塊的名字必須是符合變量命名規範的
技術分享圖片
1-5、本文件中存在與導入模塊相同的變量 # My_module中的內容: name = 帥鍋 def read(): print(in read,name) # 執行文件的內容: import My_module My_module.read() # in read 帥鍋 name = SB My_module.read() # in read 帥鍋 My_module.name = SB My_module.read() # in read SB 總結: 在本文件中定義了一個與導入模塊相同的變量, 並不會影響導入模塊中的變量,因為這兩個變量是存在不同的命名空間中的,互不影響。 1-6、本文件中存在一個變量,這個變量名是導入的模塊名 這個時候就相當於把指向導入模塊的指針斷開了,再指向新的值 My_module = 1 print(My_module) # 1 My_module.read() #報錯
技術分享圖片
    
1-7、一次導入多個模塊的方式
import os,time,My_module
但是一般不建議這麽使用,因為根據pep8規範(python編寫規範):
我們導入模塊的順序應該是:內置模塊,第三方模塊,自定義模塊
import os          # 內置
import time      # 內置

import django  # 第三方

import my_module  # 自定義


1-8、給模塊起別名,一旦給模塊起了別名,那麽原名就不能使用了
import My_module as m
print(m.name)  # 帥鍋
print(My_module.name)  # 報錯


1-9、如何判斷模塊能否被導入
sys.path是一個存放了所有模塊路徑的列表,
一個模塊是否能被導入,就看這個模塊所在的目錄在不在sys.path中,
如果這個模塊的路徑不在sys.path中,那麽就不可被導入,
不過可以自己手動添加:sys.path.append(“自定義的模塊路徑”)
    

    
1-10、循環引用模塊(看圖) 
技術分享圖片
1-11、運行一個py文件的兩種方式方式 1,直接運行它 : 在cmd終端運行: python xx.py 或者在pycharm中直接運行 當用這種方式運行這個py文件,那麽這個py文件就稱為:腳本 這個時候py文件中的:__name__ == __main__ 2,導入它 : 導入一個模塊,也會運行一次這個py文件 當用這種方式運行py文件,這個py文件就稱為:模塊 這個時候py文件中的:__name__ == 模塊名 import My_module __name__ = my_module 例如: 在My_module中有這樣的代碼: print(in mymodule) print(__name__ : ,__name__) 那麽直接在My_module中運行結果為:in mymodule __name__ : __main__ 在導入My_module的文件中執行導入模塊(會默認執行一次My_module) import My_module 然後執行,結果為:in mymodule __name__ : My_module 2、from xx import xx 2-1在from import的過程中發生了哪些事情 from My_module import name from My_module import read 1,要找到My_module 2,開空間,執行my_module 3,所有的My_module中的名字都存儲在My_module所屬的空間中 4,本文件空間中建立對應的變量名(name,read),分別取引用My_module空間中對應的名字 from My_module import name from My_module import read print(name) # 帥鍋 read() # in read 帥鍋
技術分享圖片

2-2、引用模塊的變量後,進行修改(看圖)
from My_module import name
from My_module import read
print(name)   # 帥鍋

name = aaa
read()            # in read 帥鍋

print(name)  # aaa
技術分享圖片

2-3、from import 多個內容 from My_module import name,read,read2 2-4、給導入的內容起別名 from My_module import name as n,read as r,read2 as r2 2-5、from import *和 __all__關系 1,只有from import * 沒有__all__的時候,My_module的所有變量都可以在本文件中使用 from My_module import * print(name) # 帥鍋 read() # in read 帥鍋 read2() # in read2 帥鍋 2,即有from import * 也有__all__的時候,只有被__all__聲明的變量才能在本文件中使用 My_module中:__all__ = [name,read] 本文件中執行: from My_module import * print(name) # 帥鍋 read() # in read 帥鍋 read2() # 報錯:name ‘read2‘ is not defined 2-6、模塊的導入和修改 模塊在導入後,在程序運行期間,你再去修改導入的模塊,導入的內容依舊是不變的。 如果硬是要在程序運行期間修改模塊的內容,並讓修改的內容生效,那麽可以使用reload. from importlib import reload ‘‘‘ 在這期間修改模塊的內容 ‘‘‘ # 重新reload,修改的內容就生效了 reload(My_module) 3、補充的內容 1.pyc文件、pyi文件 * pyc文件是導入包的時候自動產生的字節碼文件,只能提高程序的啟動效率並不能提高程序的執行效率 2.模塊的導入和修改 * 3.模塊的循環引用 **** 不能循環 4.dir(模塊名) *** 可以獲取這個模塊中的所有名字 二、導入包 11.無論是import形式還是from...import形式,凡是在導入語句中遇到帶點的都是關於包的導入語法。 2. 包是目錄級的(文件夾級),文件夾是用來組成py文件(包的本質就是一個包含__init__.py文件的目錄) 3. import導入文件時,產生名稱空間中的名字來源於文件,import 包,產生的名稱空間的名字同樣來源於文件,即包下的__init__.py,導入包本質就是在導入該文件 4.導入包就相當於執行力這個包下的__init__.py文件,在__init__下導入了什麽模塊,你就等於導入了什麽模塊 強調:   1. 在python3中,即使包下沒有__init__.py文件,import 包仍然不會報錯,而在python2中,包下一定要有該文件,否則import 包會報錯   2. 創建包的目的不是為了運行,而是被導入使用,記住,包只是模塊的一種形式而已,包即模塊 2、目錄結構創建 創建代碼目錄: import os os.makedirs(glance/api) os.makedirs(glance/cmd) os.makedirs(glance/db) l = [] l.append(open(glance/__init__.py,w)) l.append(open(glance/api/__init__.py,w)) l.append(open(glance/api/policy.py,w)) l.append(open(glance/api/versions.py,w)) l.append(open(glance/cmd/__init__.py,w)) l.append(open(glance/cmd/manage.py,w)) l.append(open(glance/db/models.py,w)) map(lambda f:f.close() ,l) 目錄結構: glance/ #Top-level package ├── __init__.py #Initialize the glance package ├── api #Subpackage for api │ ├── __init__.py │ ├── policy.py │ └── versions.py ├── cmd #Subpackage for cmd │ ├── __init__.py │ └── manage.py └── db #Subpackage for db ├── __init__.py └── models.py 文件內容 #policy.py def get(): print(from policy.py) #versions.py def create_resource(conf): print(from version.py: ,conf) #manage.py def main(): print(from manage.py) #models.py def register_models(engine): print(from models.py: ,engine) 3、註意事項 1.關於包相關的導入語句也分為import和from ... import ...兩種,但是無論哪種,無論在什麽位置,在導入時都必須遵循一個原則: 凡是在導入時帶點的,點的左邊都必須是一個包,右邊可以是包也可以是文件,否則非法。可以帶有一連串的點,如glance.db.models,但都必須遵循這個原則。 2.對於導入後,在使用時就沒有這種限制了,點的左邊可以是包,模塊,函數,類(它們都可以用點的方式調用自己的屬性)。 4、import:import什麽,調用的時候就要寫全 import glance.db.models glance.db.models.register_models(hello) # from models.py: hello 5、from...import 需要註意的是from後import導入的模塊,必須是明確的一個不能帶點,否則會有語法錯誤,如:from a import b.c是錯誤語法 from glance.db import models models.register_models(hello) from glance.db.models import register_models register_models(hello) 6、__init__.py文件 不管是哪種方式,只要是第一次導入包或者是包的任何其他部分,都會依次執行包下的__init__.py文件, 也就是說每次導入一個包都會先執行包下的__init__.py文件。 在包api下的__init__.py文件寫入這樣的代碼: print(__init__) __all__ = [policy] 然後在主程序執行: from glance.api import * policy.get() # __init__ # from policy.py versions.create_resource(aa) # 報錯:name ‘versions‘ is not defined 7、絕對導入和相對導入 我們的最頂級包glance是寫給別人用的,然後在glance包內部也會有彼此之間互相導入的需求,這時候就有絕對導入和相對導入兩種方式: 絕對導入:以glance作為起始 相對導入:用.或者..的方式最為起始(只能在一個包中使用,不能用於不同目錄內) 一旦使用了相對導入,那麽這個文件只能作為模塊使用,不用直接執行了。 8、單獨導入包 直接單獨導入包,比如import glance,是不會導入包中的模塊的, 直接導入包名稱的時候,只會去執行包中的__init__文件,所以單獨導入包名稱的時候,需要 去包下的__init__文件中導入相應的模塊。 例如:在與glance同級的test.py文件下運行代碼: import glance glance.api.policy.get() # 報錯:module ‘glance‘ has no attribute ‘api‘ 導入包就等於導入包下__init__的內容,而此時在glance的__init__內沒有導入相應的內容,所以會報錯 在glance包下的__init__寫入: from glance.api import policy 再次執行 import glance glance.api.policy.get() 結果:from policy.py 三、開發規範(插圖)
技術分享圖片

python之模塊、包的導入過程和開發規範