python3-基礎8

模塊與包python

什麼是模塊json

 模塊就是一個包含了python定義和聲明的文件,文件名就是模塊名字加上.py的後綴。api

#在python中,模塊的使用方式都是同樣的,但其實細說的話,模塊能夠分爲四個通用類別: app

  1 使用python編寫的.py文件,是被導入使用的函數

  2 已被編譯爲共享庫或DLL的C或C++擴展編碼

  3 把一系列模塊組織到一塊兒的文件夾(注:文件夾下有一個__init__.py文件,該文件夾稱之爲包),包就是包含init的文件夾,也是被導入使用的spa

  4 使用C編寫並連接到python解釋器的內置模塊命令行

 

導入模塊幹了那些事日誌

一、執行源文件code

二、以源文件爲基礎產生一個全局名稱空間,若是調用源空間中的函數,用.就行,做用域關係在調用的時候就已經固定了。

三、再當前位置拿到一個模塊名,指向2建立的名稱空間

 

import 使用

別名   用 as

1 import spam as sm

2 print(sm.money)

 

一行中導入多個模塊,用逗號隔開
import os,sys,spam

自定義模塊、內置模塊、第三方模塊、包 等等

 

from ... inmport ... 用法

from...import * # *表明全部(除了橫杆開頭的名字,如 _money()),通常不建議用,
#也能夠在模塊開頭增長 __all__=['money','x','y'] 來控制*的識別範圍,
#_ 和 __all__ 只是對from...import * 有用

#from sys import * 把spam中全部的不是如下劃線(_)開頭的名字都導入到當前位置

#大部分狀況下咱們的python程序不該該使用這種導入方式,由於*你不知道你導入什麼名字,頗有可能會覆蓋掉你以前已經定義的名字。並且可讀性極其的差,在交互式環境中導入時沒有問題。

#優勢:使用源文件內的名字時無需加前綴,使用方便
#缺點:容易與當前文件的名稱空間內的名字混淆

#能夠起別名
# from spam import money as m

==============
'''
查找模塊
模塊只有在第一次導入時纔會執行,以後的導入都是直接引用內存中已經存在的結果

import sys
print(sys.modules) #一個字典,存放的是已經加載到內存的模塊
print(sys.path) #一個列表,存放的是當前執行文件的路徑

模塊的搜索路徑
import sys
先從哪裏找?
先從內存裏找,而後再去硬盤上找

python文件修改完後必定要重啓程序,從新加載一遍纔會生效

模塊的查找順序是:內存中已經加載的模塊->內置模塊->sys.path路徑中包含的模塊
好比找abc\abc.py模塊,若內存中和硬盤中都找不到,那就要去sys.path中找,這就須要吧abc.py所在的目錄路徑添加到sys.path裏去
sys.path.append(r'C:\Users\Administrator\PycharmProjects\python\abc') #將目錄添加到最後
sys.path.insert(0,r'C:\Users\Administrator\PycharmProjects\python\abc') #將目前插到最前面,找到的更快

注意:自定義的模塊必定不要與python自帶的模塊名重名

要明確 執行文件是誰,被導入的文件是誰

'''
'''
兩種使用方法:
被當作腳本使用
被當作模塊使用

__name__
#文件當作腳本運行時__name__等於__main__
#文件當作模塊被加載運行時__name__等於模塊名

寫模塊時添加以下代碼(只有被當作腳本使用時,纔會執行if裏的代碼):
if __name__ == '__main__':
#當作腳本使用
func1()
func2()
func3()

#導入模塊實際上就是導入文件下的 __init__.py 文件
#開發者經過修改 __init__.py 文件,方便使用者調用函數

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

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

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

三步:

一、執行文件

二、產生名稱空間

三、調用函數

 

絕對導入與相對導入

咱們的最頂級包glance是寫給別人用的,而後在glance包內部也會有彼此之間互相導入的需求,這時候就有絕對導入和相對導入兩種方式:

絕對導入:以glance做爲起始

相對導入:用.或者..的方式最爲起始(只能在一個包中使用,不能用於不一樣目錄內)

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


# 絕對導入: 以執行文件的sys.path爲起始點開始導入,稱之爲絕對導入
# 優勢: 執行文件與被導入的模塊中均可以使用
# 缺點: 全部導入都是以sys.path爲起始點,導入麻煩

# 相對導入: 參照當前所在文件的文件夾爲起始開始查找,稱之爲相對導入
# 符號: .表明當前所在文件的文件加,..表明上一級文件夾,...表明上一級的上一級文件夾
# 優勢: 導入更加簡單
# 缺點: 只能在導入包中的模塊時才能使用
     #注意:
    1. 相對導入只能用於包內部模塊之間的相互導入,導入者與被導入者都必須存在於一個包內
    2. attempted relative import beyond top-level package # 試圖在頂級包以外使用相對導入是錯誤的,言外之意,必須在頂級包內使用相對導入,每增長一個.表明跳到上一級文件夾,而上一級不該該超出頂級包

 

軟件開發規範:
    bin   目錄下是執行文件
    conf 目錄下是控制文件
    lib    目錄下是本程序須要依賴或開發的功能模塊文件
    log   目錄下是日誌文件
    db    目錄下存放數據文件
    core 目錄下存放核心的邏輯

    Readme

示例  :

  1 ###############
  2 #===============>star.py
  3 import sys,os
  4 ##該文件所在位置:D:\第1層\第2層\第3層\第4層\第5層\test_gfh.py
  5 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  # 獲取當前運行腳本的絕對路徑
  6 '''
  7 若是直接在python console 中或者命令行中運行上面代碼,則會報以下錯誤:
  8 NameError: name '__file__' is not defined
  9 
 10 緣由是:‘__file__'這個參數表明的是python解釋器正在執行的腳本文件,若是直接在命令行運行上面兩行代碼,則python解釋器找不到正在執行的腳本文件,即咱們將它寫在一個腳本文件中,再在解釋器中運行這個腳本文件就ok了
 11 
 12 '''
 13 sys.path.append(BASE_DIR) #將路徑添加到sys.path
 14 
 15 from core import src
 16 
 17 if __name__ == '__main__':
 18     src.run()
 19 #===============>settings.py
 20 import os
 21 
 22 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 23 DB_PATH=os.path.join(BASE_DIR,'db','db.json')
 24 LOG_PATH=os.path.join(BASE_DIR,'log','access.log')
 25 LOGIN_TIMEOUT=5
 26 
 27 """
 28 logging配置
 29 """
 30 # 定義三種日誌輸出格式
 31 standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
 32                   '[%(levelname)s][%(message)s]' #其中name爲getlogger指定的名字
 33 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
 34 id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
 35 
 36 # log配置字典
 37 LOGGING_DIC = {
 38     'version': 1,
 39     'disable_existing_loggers': False,
 40     'formatters': {
 41         'standard': {
 42             'format': standard_format
 43         },
 44         'simple': {
 45             'format': simple_format
 46         },
 47     },
 48     'filters': {},
 49     'handlers': {
 50         #打印到終端的日誌
 51         'console': {
 52             'level': 'DEBUG',
 53             'class': 'logging.StreamHandler',  # 打印到屏幕
 54             'formatter': 'simple'
 55         },
 56         #打印到文件的日誌,收集info及以上的日誌
 57         'default': {
 58             'level': 'DEBUG',
 59             'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
 60             'formatter': 'standard',
 61             'filename': LOG_PATH,  # 日誌文件
 62             'maxBytes': 1024*1024*5,  # 日誌大小 5M
 63             'backupCount': 5,
 64             'encoding': 'utf-8',  # 日誌文件的編碼,不再用擔憂中文log亂碼了
 65         },
 66     },
 67     'loggers': {
 68         #logging.getLogger(__name__)拿到的logger配置
 69         '': {
 70             'handlers': ['default', 'console'],  # 這裏把上面定義的兩個handler都加上,即log數據既寫入文件又打印到屏幕
 71             'level': 'DEBUG',
 72             'propagate': True,  # 向上(更高level的logger)傳遞
 73         },
 74     },
 75 }
 76 
 77 
 78 #===============>src.py
 79 from conf import settings
 80 from lib import common
 81 import time
 82 
 83 logger=common.get_logger(__name__)
 84 
 85 current_user={'user':None,'login_time':None,'timeout':int(settings.LOGIN_TIMEOUT)}
 86 def auth(func):
 87     def wrapper(*args,**kwargs):
 88         if current_user['user']:
 89             interval=time.time()-current_user['login_time']
 90             if interval < current_user['timeout']:
 91                 return func(*args,**kwargs)
 92         name = input('name>>: ')
 93         password = input('password>>: ')
 94         db=common.conn_db()
 95         if db.get(name):
 96             if password == db.get(name).get('password'):
 97                 logger.info('登陸成功')
 98                 current_user['user']=name
 99                 current_user['login_time']=time.time()
100                 return func(*args,**kwargs)
101         else:
102             logger.error('用戶名不存在')
103 
104     return wrapper
105 
106 @auth
107 def buy():
108     print('buy...')
109 
110 @auth
111 def run():
112 
113     print('''
114 購物
115 查看餘額
116 轉帳
117     ''')
118     while True:
119         choice = input('>>: ').strip()
120         if not choice:continue
121         if choice == '1':
122             buy()
123 
124 
125 
126 #===============>db.json
127 {"egon": {"password": "123", "money": 3000}, "alex": {"password": "alex3714", "money": 30000}, "wsb": {"password": "3714", "money": 20000}}
128 
129 #===============>common.py
130 from conf import settings
131 import logging
132 import logging.config
133 import json
134 
135 def get_logger(name):
136     logging.config.dictConfig(settings.LOGGING_DIC)  # 導入上面定義的logging配置
137     logger = logging.getLogger(name)  # 生成一個log實例
138     return logger
139 
140 
141 def conn_db():
142     db_path=settings.DB_PATH
143     dic=json.load(open(db_path,'r',encoding='utf-8'))
144     return dic
145 
146 
147 #===============>access.log
148 [2017-10-21 19:08:20,285][MainThread:10900][task_id:core.src][src.py:19][INFO][登陸成功]
149 [2017-10-21 19:08:32,206][MainThread:10900][task_id:core.src][src.py:19][INFO][登陸成功]
150 [2017-10-21 19:08:37,166][MainThread:10900][task_id:core.src][src.py:24][ERROR][用戶名不存在]
151 [2017-10-21 19:08:39,535][MainThread:10900][task_id:core.src][src.py:24][ERROR][用戶名不存在]
相關文章
相關標籤/搜索