Python進階-XIII 導入模塊和包 異常處理

1、模塊的導入python

1)、importmysql

 1 # 測試一:money與my_module.money不衝突
 2 import my_module
 3 money=10
 4 print(my_module.money)
 5 
 6 '''
 7 執行結果:
 8 from the my_module.py
 9 1000
10 '''
11 
12 #測試二:read1與my_module.read1不衝突
13 
14 import my_module
15 def read1():
16     print('========')
17 my_module.read1()
18 
19 #測試三:執行my_module.change()操做的全局變量money仍然是my_module中的
20 #demo.py
21 import my_module
22 money=1
23 my_module.change()
24 print(money)
25 
26 '''
27 執行結果:
28 from the my_module.py
29 1
30 '''
31 
32 '''
33 執行結果:
34 from the my_module.py
35 my_module->read1->money 1000
36 '''
View Code

首次導入模塊my_module時會作三件事:web

(1). 爲源文件(my_module模塊)建立新的名稱空間,在my_module中定義的函數和方法如果使用到了global時訪問的就是這個名稱空間。
(2). 在新建立的命名空間中執行模塊中包含的代碼,見初始導入import my_module
(3). 建立名字my_module來引用該命名空間

補充:能夠爲模塊名起別名 如:import xmlreader as reader
 1 import my_module as sm
 2 print(sm.money)
 3 # 示範用法一:
 4 # 有兩中sql模塊mysql和oracle,根據用戶的輸入,選擇不一樣的sql功能
 5 def sqlparse():
 6     print('from mysql sqlparse')
 7 #oracle.py
 8 def sqlparse():
 9     print('from oracle sqlparse')
10 
11 #test.py
12 db_type=input('>>: ')
13 if db_type == 'mysql':
14     import mysql as db
15 elif db_type == 'oracle':
16     import oracle as db
17 
18 db.sqlparse()
19 
20 # 示範用法二:
21 # 爲已經導入的模塊起別名的方式對編寫可擴展的代碼頗有用,假設有兩個模塊xmlreader.py和csvreader.py,
22 # 它們都定義了函數read_data(filename):用來從文件中讀取一些數據,但採用不一樣的輸入格式。能夠編寫代碼來選擇性地挑選讀取模塊,例如
23 if file_format == 'xml':
24      import xmlreader as reader
25 elif file_format == 'csv':
26      import csvreader as reader
27 data=reader.read_date(filename)
View Code

能夠在一行導入多個模塊,如:sql

import sys,os,re

2)、from importjson

 

對比import my_module,會將源文件的名稱空間'my_module'帶到當前名稱空間中,使用時必須是my_module.名字的方式
而from 語句至關於import,也會建立新的名稱空間,可是將my_module中的名字直接導入到當前的名稱空間中,在當前名稱空間中,直接使用名字就能夠了:如
from my_module import read1,read2
樣在當前位置直接使用read1和read2就行了,執行時,仍然以my_module.py文件全局名稱空間
 1 #測試一:導入的函數read1,執行時仍然回到my_module.py中尋找全局變量money
 2 
 3 from my_module import read1
 4 money=1000
 5 read1()
 6 '''
 7 執行結果:
 8 from the my_module.py
 9 spam->read1->money 1000
10 '''
11 
12 #測試二:導入的函數read2,執行時須要調用read1(),仍然回到my_module.py中找read1()
13 from my_module import read2
14 def read1():
15     print('==========')
16 read2()
17 
18 '''
19 執行結果:
20 from the my_module.py
21 my_module->read2 calling read1
22 my_module->read1->money 1000
23 '''
24 
25 # 若是當前有重名read1或者read2,那麼會有覆蓋效果。
26 
27 # 測試三:導入的函數read1,被當前位置定義的read1覆蓋掉了
28 
29 from my_module import read1
30 def read1():
31     print('==========')
32 read1()
33 '''
34 執行結果:
35 from the my_module.py
36 ==========
37 '''
38 # 須要特別強調的一點是:python中的變量賦值不是一種存儲操做,而只是一種綁定關係,以下:
39 from my_module import money,read1
40 money=100  # 將當前位置的名字money綁定到了100
41 print(money)  # 打印當前的名字
42 read1()  # 讀取my_module.py中的名字money,仍然爲1000
43 
44 # 也支持as
45 from my_module import read1 as read
46 
47 # 也支持導入多行
48 from my_module import (read1,
49                    read2,
50                   money)
51 
52 '''
53 from the my_module.py
54 100
55 my_module->read1->money 1000
56 '''
57 
58 # from my_module import * 把my_module中全部的不是如下劃線(_)開頭的名字都導入到當前位置,大部分狀況
59 # 下咱們的python程序不該該使用這種導入方式,由於*你不知道你導入什麼名字,頗有可能會覆蓋掉你以前已經定義的名字。
60 #  並且可讀性極其的差,在交互式環境中導入時沒有問題。
61 
62 from my_module import * #將模塊my_module中全部的名字都導入到當前名稱空間
63 print(money)
64 print(read1)
65 print(read2)
66 print(change)
67 
68 '''
69 執行結果:
70 from the my_module.py
71 1000
72 <function read1 at 0x1012e8158>
73 <function read2 at 0x1012e81e0>
74 <function change at 0x1012e8268>
75 '''
76 
77 # 在my_module.py中新增一行
78 __all__=['money','read1'] #這樣在另一個文件中用from my_module import *就這能導入列表中規定的兩個名字
79 # *若是my_module.py中的名字前加_,即_money,則from my_module import *,則_money不能被導入
View Code

 

2、包的導入api

1)、常見非web項目的包結構oracle

softapp

++binide

++++start.py函數

++conf

++++config.ini

++++my_log_settings.py

++++settings.py

++core

++++core.py

++db

++++some_db.json

++lib

++++some_lib.py

++log

++++some_log.py

建立代碼

 1 import os
 2 os.makedirs('soft/bin')
 3 os.makedirs('soft/conf')
 4 os.makedirs('soft/core')
 5 os.makedirs('soft/db')
 6 os.makedirs('soft/lib')
 7 os.makedirs('soft/log')
 8 
 9 l = []
10 l.append(open('soft/__init__.py', 'w'))
11 l.append(open('soft/bin/__init__.py', 'w'))
12 l.append(open('soft/bin/start.py', 'w'))
13 l.append(open('soft/conf/__init__.py', 'w'))
14 l.append(open('soft/conf/config.ini', 'w'))
15 l.append(open('soft/conf/my_log_settings.py', 'w'))
16 l.append(open('soft/conf/settings.py', 'w'))
17 l.append(open('soft/core/__init__.py', 'w'))
18 l.append(open('soft/db/__init__.py', 'w'))
19 l.append(open('soft/lib/__init__.py', 'w'))
20 l.append(open('soft/log/__init__.py', 'w'))
21 
22 map(lambda f:f.close(), l)
View Code

 

2)、注意事項

 (1).關於包相關的導入語句也分爲import和from ... import ...兩種,可是不管哪一種,不管在什麼位置,在導入時都必須遵循一個原則:
凡是在導入時帶點的,點的左邊都必須是一個包,不然非法。
   能夠帶有一連串的點,如item.subitem.subsubitem,但都必須遵循這個原則。
(2).對於導入後,在使用時就沒有這種限制了,點的左邊能夠是包,模塊,函數,類(它們均可以用點的方式調用本身的屬性)。
(3).對比import item 和from item import name的應用場景:
     若是咱們想直接使用name那必須使用後者。

3)、具體使用
(1)import
咱們在與包glance同級別的文件中測試
import glance.db.models  # 雖然有報錯,可是正確的!
glance.db.models.register_models('mysql')
(2)from import
須要注意的是from後import導入的模塊,必須是明確的一個不能帶點,不然會有語法錯誤,如:from a import b.c是錯誤語法
咱們在與包glance同級別的文件中測試
# from glance.db import models
# models.register_models('oracle')
# 還能夠
# from glance.db.models import register_models
# register_models('mysql')

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

(4)from glance.api import *
在講模塊時,咱們已經討論過了從一個模塊內導入全部*,此處咱們研究從一個包導入全部*。 此處是想從包api中導入全部,實際上該語句只會導入包api下__init__.py文件中定義的名字,咱們能夠在這個文件中定義__all___:
# x=10
# def func():
# print('from api.__init.py')
# __all__=['x','func','policy']
#此時咱們在於glance同級的文件中執行
# from glance.api import *
# 就導入__all__中的內容(versions仍然不能導入)。
# func()
# policy.get()
# versions.create_resource('mysql') #NameError: name 'versions' is not defined

(5)絕對導入和相對導入
 咱們的最頂級包glance是寫給別人用的,而後在glance包內部也會有彼此之間互相導入的需求,這時候就有絕對導入和相對導入兩種方式:
絕對導入:以glance做爲起始(要看sys.path()中的路徑是否包含該路徑!)
from glance.cmd import manage
manage.main()
相對導入:用.或者..的方式最爲起始(只能在一個包中使用,不能用於不一樣目錄內)
例如:咱們在glance/cmd/manage.py中想要導入glance/api/version.py
from ..api import policy
可是不能在該py文件中直接運行,要從該文件所在包之外的地方調用,纔會有效果!

三、異常處理
1)、各類狀況下的錯誤示例
1/0 ZeroDivisionError: division by zero
name NameError: name 'name' is not defined
2+'3' TypeError: unsupported operand type(s) for +: 'int' and 'str'
[][3] IndexError: list index out of range
{}['k'] KeyError: 'k'
2)、使用try捕獲錯誤,進行處理
1)、except 捕獲錯誤 進行處理
2)、else 若是try中的語句沒有錯誤,執行的代碼。
3)、finally 不論是否有錯誤,都會執行的代碼
 1 try:
 2     print('1111')
 3     # 1/0
 4     print('2222')
 5     # name
 6     # 2+'3'
 7     # [][3]
 8     # {}['k']
 9     ret = int(input('number >>>'))
10     print(ret*'*')
11 except ValueError:
12     print('輸入的數據類型有誤')
13 except Exception:
14     print('你錯了,老鐵')
15 else:
16     print('沒有異常的時候執行else中的代碼')
17 print('===========')
18 def func():
19     try:
20         f = open('file','w')
21         ''''''
22         return True
23     except:
24         return False
25     finally:
26         print('執行finally了')
27         f.close()
28 
29 print(func())
View Code
三、注意事項
程序一旦發生錯誤,就從錯誤的位置停下來了,不在繼續執行後面的內容
使用try和except就能處理異常
try是咱們須要處理的代碼
except 後面跟一個錯誤類型 當代碼發生錯誤且錯誤類型符合的時候 就會執行except中的代碼
except支持多分支
有沒有一個能處理全部錯誤的類型 : Exception
有了萬能的處理機制仍然須要把能預測到的問題單獨處理
單獨處理的全部內容都應該寫在萬能異常以前
else : 沒有異常的時候執行else中的代碼
finally : 無論代碼是否異常,都會執行
finally和return相遇的時候 依然會執行
函數裏作異常處理用,不論是否異常去作一些收尾工做
ry:
    print('1111')
    # 1/0
    print('2222')
    # name
    # 2+'3'
    # [][3]
    # {}['k']
    ret = int(input('number >>>'))
    print(ret*'*')
except Exception as error:
    print('你錯了,老鐵',error)
相關文章
相關標籤/搜索