摘要:導入模塊、導入包、編程規范
以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(模塊名) ***
可以獲取這個模塊中的所有名字
二、導入包
1、
1.無論是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
三、開發規范(插圖)
