019_包 和 異常處理

1,包
  1.1,把解決一類問題的模塊放在同一個文件夾裏 —— 包
  1.2,包是一種經過使用‘.模塊名’來組織python模塊名稱空間的方式。

  1.3, 不管是import形式仍是from...import形式,凡是在導入語句中(而不是在使用時)遇到帶點的,都要第一時間提升警覺:這是關於包纔有的導入語法
  1.4,包是目錄級的(文件夾級),文件夾是用來組成py文件(包的本質就是一個包含__init__.py文件的目錄)
  1.5, import導入文件時,產生名稱空間中的名字來源於文件,import 包,產生的名稱空間的名字一樣來源於文件,即包下的__init__.py,導入包本質就是在導入該文件

  強調
    1. 在python3中,即便包下沒有__init__.py文件,import 包仍然不會報錯,而在python2中,包下必定要有該文件,不然import 包報錯
    2. 建立包的目的不是爲了運行,而是被導入使用,記住,包只是模塊的一種形式而已,包即模塊
    3.包A和包B下有同名模塊也不會衝突,如A.a與B.a來自倆個命名空間
2,關於導入的兩種方式
  2.1,關於包相關的導入語句也分爲import和from ... import ...兩種,可是不管哪一種,不管在什麼位置,在導入時都必須遵循一個原則:凡是在導入時帶點的,點的左邊都必須是一個包,不然非法。能夠帶有一連串的點,如item.subitem.subsubitem,但都必須遵循這個原則。
  2.2,對於導入後,在使用時就沒有這種限制了,點的左邊能夠是包,模塊,函數,類(它們均可以用點的方式調用本身的屬性)。
  2.3,對比import item 和from item import name的應用場景:若是咱們想直接使用name那必須使用後者。
 
3,兩個與導入模塊緊密相關的
  • sys.moudles   記錄了全部被導入的模塊
  • sys.path         記錄了導入模塊的時候尋找的全部路徑

4,建立包練習的程序python

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)

文件內容

5,import 方法導入和使用mysql

  咱們在與包glance同級別的文件中測試,此驗證程序寫在與glance同一文件加下。sql

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

 

6,from ... import ...方法導入和使用數據庫

  6.1,api

  • 須要注意的是from後import導入的模塊,必須是明確的一個不能帶點,不然會有語法錯誤,如:from a import b.c是錯誤語法
  • 該導入方式必須從與該文件同目錄下的同級別文件開始導入。且只能導入同目錄下同級別模塊的方法或級別包下的內容。
  • 由於,執行該模塊時,在sys.path中記錄到該模塊的路徑,因此,from只有從該模塊同級別的文件開始導入才能成功

 

  6.2,咱們在與包glance同級別的文件中測試app

from glance.db import models     #導入包中的一個模塊
models.register_models('mysql')   #從導入到模塊調用模塊內函數

from glance.db.models import register_models   #能夠只導入其中的一個方法
register_models('mysql')

7,關於 __init__.py文件運維

  不論是哪一種方式,只要是第一次導入包或者是包的任何其餘部分,都會依次執行包下的__init__.py文件(咱們能夠在每一個包的文件內都打印一行內容來驗證一下),這個文件能夠爲空,可是也能夠存放一些初始化包的代碼。ide

 8,關於從包中導入全部包中的模塊函數

  導入一個設計好的使用該語句  from glance.api import *
      此處是想從包api中導入全部,實際上該語句只會導入包api下__init__.py文件並執行,咱們能夠在這個文件中定義「__all__ = ['模塊名']」,來實現導入包內全部模塊。測試

# 在api包內的__init__.py文件里加入「__all__ = ['policy','versions']」
from glance.api import *
policy.get()

9,咱們在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

  在version.py寫入的語句若是在version.py開始執行(即按下run),會報錯,找不到。由於不是從與version.py同級別的文件開始導入的。

  可是,按上面的方法卻能夠,是由於from glance.api import versions執行的時候已經將到達glance的路徑加載在sys.path中了,因此在version.py中可以從glance開始導入。

10,   

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

好比咱們想在glance/api/versions.py中導入glance/api/policy.py,

#在version.py中
import policy
policy.get()

  沒錯,咱們單獨運行version.py是一點問題沒有的,運行version.py的路徑搜索就是從當前路徑開始的,因而在導入policy時能在當前目錄下找到

  可是你想啊,你子包中的模塊version.py極有多是被一個glance包同一級別的其餘文件導入,好比咱們在於glance同級下的一個test.py文件中導入version.py就會找不到要導入包的路徑

11,能夠經過修改sys.path保存的路徑進行修改

import sys
sys.path.insert(0,'C:\\Users\\Administrator\\PycharmProjects\\s9\\day21\\dir')
# print(sys.path)
from glance.api import policy
policy.get() 

12,建立包
  12.1,在python2中包裏必須有__init__.py文件,python3中能夠沒有,但不影響使用。
    在導入包的時候,就會執行__init__.py所以,能夠利用這一特性將包內的其餘模塊(即py文件)導入。這樣在只導入這個包的後,可以使用包內的其餘模塊。而不須要須要該模塊時再去導入。
from dir import glance
glance.db.models.register_models('mysql')
glance.api.policy.get()
    以上爲絕對路徑:
    使用絕對路徑 無論在包內部仍是外部 導入了就能用,不能挪動,可是直觀
  12.2,一個‘.’表明當前路徑,‘..’表明上一個目錄
form . import api
form . import cmd
    相對路徑
    能夠隨意移動包 只要能找到包的位置,就可使用包裏的模塊
    包裏的模塊若是想使用其它模塊的內容只能使用相對路徑,使用了相對路徑就不能在包內直接執行
13,建立項目時建立包的結構
    bin       start文件,     程序入口 
    conf     給運維人員看的,配置文件
    core     代碼文件,      核心代碼
    db   數據,  數據庫
    lib   本身寫的包,模塊
    log    程序的運行報告,  日誌
14,
import os
import sys
sys.path.append(os.path.dirname(os.getcwd()))
 #獲取當前路徑的上一個目錄的路徑,並將路徑添加到sys.path中,這樣即便不是在pycharm中也能執行了。
from core import core
if __name__ == '__main__':
    core.main()
 
15,異常和錯誤
    程序中不免出現錯誤,而錯誤分紅兩種
        1.語法錯誤(這種錯誤,根本過不了python解釋器的語法檢測,必須在程序執行前就改正)
        2.邏輯錯誤(邏輯錯誤
16,異常處理
  16.1,程序一旦發生錯誤,就從錯誤的位置停下來了,不在繼續執行後面的內容。若是不想程序報錯,就對錯誤進行處理。
try:
    ret = int(input('number>>>'))
    print(ret*'*')
except ValueError:
    print('您輸入的內容有錯,請輸入一個數字')
except Exception:
    print('你錯了,老鐵')
else:
    print('沒有異常的時候執行else中的代碼')
print('===========')
  格式:
try:
     被檢測的代碼塊
except 異常類型:
     try中一旦檢測到異常,就執行這個位置的邏輯
  支持多分支
s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)
except ValueError as e:
    print(e)
  16.2,使用 try 和 except 就能處理異常
      try    是咱們須要處理的代碼
      except   後面跟一個錯誤類型 當代碼發生錯誤且錯誤類型符合的時候 就會執行except中的代碼
      except  支持多分支
      Exception 能處理全部錯誤的類型
              有了萬能的處理機制仍然須要把能預測到的問題單獨處理
              單獨處理的全部內容都應該寫在萬能異常以前
      else   沒有異常的時候執行else中的代碼
      finally  無論代碼是否異常,都會執行
              finally和return相遇的時候 依然會執行
              函數裏作異常處理用,不論是否異常去作一些收尾工做
  16.3,Exception  萬能異常
    在python的異常中,有一個萬能異常:Exception,他能夠捕獲任意異常
try:
    print('1111')
    print('2222')
    ret = int(input('number >>>'))
    print(ret*'*')
except Exception as error:      #用萬能異常的時候加上‘as ereror’就會將是什麼錯誤提示出來。
    print('你錯了,老鐵',error)

  16.4,使用順序格式

s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)
except ValueError as e:
    print(e)
#except Exception as e:
#    print(e)
else:
    print('try內代碼塊沒有異常則執行我')
finally:
    print('不管異常與否,都會執行該模塊,一般是進行清理工做')

17,主動觸發異常

try:
    raise TypeError('類型錯誤')
except Exception as e:
    print(e)

# 類型錯誤

18,自定義異常

class EvaException(BaseException):
    def __init__(self,msg):
        self.msg=msg
    def __str__(self):
        return self.msg

try:
    raise EvaException('類型錯誤')
except EvaException as e:
    print(e)
	
# 類型錯誤

19,異常的關係

BaseException +-- SystemExit +-- KeyboardInterrupt +-- GeneratorExit +-- Exception +-- StopIteration +-- StandardError |    +-- BufferError |    +-- ArithmeticError |    |    +-- FloatingPointError |    |    +-- OverflowError |    |    +-- ZeroDivisionError |    +-- AssertionError |    +-- AttributeError |    +-- EnvironmentError |    |    +-- IOError |    |    +-- OSError |    |         +-- WindowsError (Windows) |    |         +-- VMSError (VMS) |    +-- EOFError |    +-- ImportError |    +-- LookupError |    |    +-- IndexError |    |    +-- KeyError |    +-- MemoryError |    +-- NameError |    |    +-- UnboundLocalError |    +-- ReferenceError |    +-- RuntimeError |    |    +-- NotImplementedError |    +-- SyntaxError |    |    +-- IndentationError |    |         +-- TabError |    +-- SystemError |    +-- TypeError |    +-- ValueError |         +-- UnicodeError |              +-- UnicodeDecodeError |              +-- UnicodeEncodeError |              +-- UnicodeTranslateError +-- Warning +-- DeprecationWarning +-- PendingDeprecationWarning +-- RuntimeWarning +-- SyntaxWarning +-- UserWarning +-- FutureWarning +-- ImportWarning +-- UnicodeWarning +-- BytesWarning
View Code
相關文章
相關標籤/搜索