鐵樂學python_day29_模塊與包學習4

来源:https://www.cnblogs.com/tielemao/archive/2018/04/28/8969791.html
-Advertisement-
Play Games

包是一種通過使用‘.模塊名’來組織python模塊名稱空間的方式。 1. 無論是import形式還是from...import形式, 凡是在導入語句中(而不是在使用時)遇到帶點的,都要第一時間提高警覺:這是關於包才有的導入語法。 2. 包是目錄級的(文件夾級),文件夾是用來組成py文件(包的本質就是... ...


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

編譯python文件

編譯python文件是為了提高載入模塊的速度,強調強調強調:提高的是載入速度而絕非運行速度。

python解釋器會在__pycache__目錄下緩存每個模塊編譯後的版本,格式為:module.version.pyc。
通常會包含python的版本號。
例如,在CPython3.3版本下,my_module.py模塊會被緩存成__pycache__/my_module.cpython-33.pyc。
這種命名規範保證了編譯後的結果多版本共存。

Python檢查源文件的修改時間與編譯的版本進行對比,如果過期就需要重新編譯。
這是完全自動的過程。並且編譯的模塊是平臺獨立的,
所以相同的庫可以在不同的架構的系統之間共用,即pyc是一種跨平臺的位元組碼,類似於JAVA和.NET,
是由python虛擬機來執行的,但是pyc的內容跟python的版本相關,不同的版本編譯後的pyc文件不同,
2.5編譯的pyc文件不能到3.5上執行,並且pyc文件是可以反編譯的,因而它的出現僅僅是用來提升模塊的載入速度的。

python解釋器在以下兩種情況下不檢測緩存。

1 如果是在命令行中被直接導入模塊,則按照這種方式,每次導入都會重新編譯,
並且不會存儲編譯後的結果(python3.3以前的版本應該是這樣)
python -m my_module.py

2 如果源文件不存在,那麼緩存的結果也不會被使用,
如果想在沒有源文件的情況下來使用編譯後的結果,則編譯後的結果必須在源目錄下。

提示:
1.模塊名區分大小寫,foo.py與FOO.py代表的是兩個模塊;
2.你可以使用-O或者-OO轉換python命令來減少編譯模塊的大小。

-O轉換會幫你去掉assert語句
-OO轉換會幫你去掉assert語句和__doc__文檔字元串
由於一些程式可能依賴於assert語句或文檔字元串,你應該在在確認需要的情況下使用這些選項。

3.在速度上從.pyc文件中讀指令來執行不會比從.py文件中讀指令執行更快,
只有在模塊被載入時,.pyc文件才是更快的。

4.只有使用import語句是才將文件自動編譯為.pyc文件,
在命令行或標準輸入中指定運行腳本則不會生成這類文件,
因而我們可以使用compieall模塊為一個目錄中的所有模塊創建.pyc文件。

模塊可以作為一個腳本(使用python -m compileall)編譯Python源

python -m compileall /module_directory 遞歸 編譯
如果使用python -O -m compileall /module_directory -l則只一層

命令行里使用compile()函數時,自動使用python -O -m compileall
詳見:https://docs.python.org/3/library/compileall.html#module-compileall

補充:dir()函數

內建函數dir是用來查找模塊中定義的名字,返回一個有序字元串列表:
import my_module
dir(my_module)

如果沒有參數,dir()列舉出當前定義的名字。

dir()不會列舉出內建函數或者變數的名字,它們都被定義到了標準模塊builtin中,可以列舉出它們,
import builtins
dir(builtins)

包是一種通過使用‘.模塊名’來組織python模塊名稱空間的方式。

1. 無論是import形式還是from...import形式,
凡是在導入語句中(而不是在使用時)遇到帶點的,都要第一時間提高警覺:這是關於包才有的導入語法。

2. 包是目錄級的(文件夾級),文件夾是用來組成py文件(包的本質就是一個包含__init__.py文件的目錄)。

3. import導入文件時,產生名稱空間中的名字來源於文件,import 包,
產生的名稱空間的名字同樣來源於文件,即包下的__init__.py,導入包本質就是在導入該文件。

強調:
1. 在python3中,即使包下沒有__init__.py文件,import 包仍然不會報錯,
而在python2中,包下一定要有該文件,否則import 包報錯。

2. 創建包的目的不是為了運行,而是被導入使用,記住,包只是模塊的一種形式而已,包即模塊。

包A和包B下有同名模塊也不會衝突,如A.a與B.a來自倆個命名空間。

以下是創建(包)目錄的代碼(腳本),以後可以在這個基礎上擴展出規範的創建腳本,自動省時:
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)

註意事項

1.關於包相關的導入語句也分為import和from ... import ...兩種,
但是無論哪種,無論在什麼位置,
在導入時都必須遵循一個原則:凡是在導入時帶點的,點的左邊都必須是一個包,否則非法。
可以帶有一連串的點,如item.subitem.subsubitem,但都必須遵循這個原則。

2.對於導入後,在使用時就沒有這種限制了,點的左邊可以是包,模塊,函數,類(它們都可以用點的方式調用自己的屬性)。
3.對比import item 和from item import name的應用場景:
如果我們想直接使用name那必須使用後者。

import

我們在與包glance同級別的文件中測試:

import glance.db.models
glance.db.models.register_models('mysql')

from ... import ...

需要註意的是from後import導入的模塊,
必須是明確的一個不能帶點,否則會有語法錯誤,如:from a import b.c是錯誤語法

我們在與包glance同級別的文件中測試
from glance.db import models
models.register_models('mysql')

from glance.db.models import register_models
register_models('mysql')

__init__.py文件
不管是哪種方式,只要是第一次導入包或者是包的任何其他部分,
都會依次執行包下的__init__.py文件(我們可以在每個包的文件內都列印一行內容來驗證一下),
這個文件可以為空,但是也可以存放一些初始化包的代碼。

from glance.api import *
在講模塊時,我們已經討論過了從一個模塊內導入所有*,此處我們研究從一個包導入所有*。
此處是想從包api中導入所有,實際上該語句只會導入包api下__init__.py文件中定義的名字,
我們可以在這個文件中定義__all___:

在__init__.py中定義
x=10

def func():
    print('from api.__init.py')

__all__=['x','func','policy']

此時我們在於glance同級的文件中執行from glance.api import *就導入__all__中的內容(versions仍然不能導入)。

from glance.api import *
glance/

├── __init__.py      
├── api                  
│   ├── __init__.py   __all__ = ['policy','versions'] 
│   ├── policy.py
│   └── versions.py
├── cmd               __all__ = ['manage']    
│   ├── __init__.py
│   └── manage.py    
└── db                __all__ = ['models']              
    ├── __init__.py
    └── models.py

from glance.api import *
policy.get()

絕對導入和相對導入

我們的最頂級包glance是寫給別人用的,然後在glance包內部也會有彼此之間互相導入的需求,
這時候就有絕對導入和相對導入兩種方式:
絕對導入:以glance作為起始
相對導入:用.或者..的方式最為起始(只能在一個包中使用,不能用於不同目錄內)

例如:我們在glance/api/version.py中想要導入glance/cmd/manage.py

在glance/api/version.py

#絕對導入
from glance.cmd import manage
manage.main()

#相對導入
from ..cmd import manage
manage.main()

測試結果:註意一定要在於glance同級的文件中測試
from glance.api import versions 

註意:在使用pycharm時,有的情況會為你多做一些事情,這是軟體相關的東西,會影響你對模塊導入的理解,
因而在測試時,一定要回到命令行去執行,模擬我們生產環境,你總不能拿著pycharm去上線代碼吧!!!

特別需要註意的是:

可以用import導入內置或者第三方模塊(已經在sys.path中),但是要絕對避免使用import來導入自定義包的子模塊(沒有在sys.path中),應該使用from... import ...的絕對或者相對導入,且包的相對導入只能用from的形式。

單獨導入包

單獨導入包名稱時不會導入包中所有包含的所有子模塊,
解決方法是子模塊中使用相對路徑引入上級(..上一級目錄)模塊或同級(.當前目錄)模塊
千萬別問:__all__不能解決嗎,__all__是用於控制from...import *

附:軟體規範開發參考目錄圖

end
2018-4-27


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ghostinit.php 用法: ghostwu@dev:~/php/php1/10$ ls ghost ghostinit.php ghostwu@dev:~/php/php1/10$ ./ghost init pls input project name? hello pls input au ...
  • Description 某天,Lostmonkey發明瞭一種超級彈力裝置,為了在他的綿羊朋友面前顯擺,他邀請小綿羊一起玩個游戲。游戲一開始,Lostmonkey在地上沿著一條直線擺上n個裝置,每個裝置設定初始彈力繫數ki,當綿羊達到第i個裝置時,它會往後彈ki步,達到第i+ki個裝置,若不存在第i+ ...
  • 實現一個功能即在站內搜索的時候敲入空格和沒有輸入的時候不會進行模糊搜索 ...
  • 嗨,我最親愛的伙計們,很高興我們又見面了。 首先先感謝朋友們的關註。當然我更希望認識與電腦相關的領域的朋友咱們一起探討交流。重點說一下,我是真人,不是那些扒文章的自媒體組織,大家可以相互交流的! 本篇文章我們來講一下關於AI相關的人臉追蹤,人臉識別相關的一些知識。當然本篇教程為(上)部分,講一下利 ...
  • 本示例以“前後端分離模式”進行演示,調試用的異常信息通過日誌的形式列印出來,代碼並不完整,僅從異常處理進行部分代碼示例。 ...
  • 1、數組 概念:一個存儲元素的線性集合。 數組聲明和創建: 二維數組(多維數組)聲明和創建: PS:數組長度必現確定的。 2、列表 概念:列表是一組有序的數據。 常用實現:ArrayList、LinkedList。 3、棧 概念:棧是一種後入先出的數據結構。 常見實現:Stack(java.util ...
  • 上一篇文章鏈接: "模仿天貓實戰【SSM版】——項目起步" 後臺需求分析 在開始碼代碼之前,還是需要先清楚自己要做什麼事情,後臺具體需要實現哪些功能: 註意: 訂單、用戶、訂單、推薦鏈接均不提供增刪的功能。 後臺界面設計 不像前端那樣有原型直接照搬就可以了,後臺的設計還真的有難到我...畢竟我是一個 ...
  • 接著之前的文章:php根據命令行參數生成配置文件 ghostinit.php ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...