模块和包
 #所有的模塊導入都應該盡量往上寫
 #內置模塊
 #擴展模塊
 #自定義模塊 寫在一個文件里
#模塊的導入過程
 #先從sys.modules里查看是否已經被導入
 #如果沒有被導入,就依據sys.path路徑尋找模塊
 #找到后就導入
 #創建整個模塊的命名空間
 #執行該文件,把文件中的名字都放到命名空間里
__all__ = ['read','read2',"money"] money = 100 def login():print('正在執行登錄程序')def read():print('in read1',money)def read2():print('in read2') print(__name__) if __name__ == '__main__':ret = login()print(ret)demo.py
?
import變量名
模塊名.變量名和文本中的變量名完全不沖突
import demo #自定義以給demo模塊 money = 11 print(demo.money) #100 print(money) #11
模塊名 as重命名的模塊名 :提高代碼的兼容性
import time print(time.localtime(1000)) #time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=8, tm_min=16, tm_sec=40, tm_wday=3, tm_yday=1, tm_isdst=0) import time as t #模塊名換成t print(t.localtime(1000))#time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=8, tm_min=16, tm_sec=40, tm_wday=3, tm_yday=1, tm_isdst=0)
imprort 模塊1,模塊2
#from 模塊名 import 變量名
# 直接使用 變量名 就可以完成操作
from math import pi print(pi) #3.141592653589793
# 如果本文件中有相同的變量名會發生沖突
from math import pi print(pi) #3.141592653589793 pi = 4 print(pi) #4View Code
?
from 模塊名 import 變量名字 as 重命名變量名
from math import pi as p print(p) # 3.141592653589793
# from 模塊名 import 變量名1,變量名2
# from 模塊名 import *
# 將模塊中的所有變量名都放到內存中
# 如果本文件中有相同的變量名會發生沖突
from demo import money print(money) #100 money = 200 print(money) #200
# from 模塊名 import * 和 __all__ 是配合用的
# 沒有沒有__all__這個變量,就會導入所有的名字
# 如果有__all__只導入all列表中的名字,且只能用列表中的變量名,其他的都不可以用
? #當__all__列表中沒有money的時候,NameError: name 'money' is not defined
#當__all__列表中有money的時候
from demo import *
print(money) #100
read() #in read1 100
import demo
print(demo.money) #100
把模塊當腳本使用
我們可以通過模塊的全局變量__name__來查看模塊名:
當做腳本運行:
__name__ 等于'__main__'
當做模塊導入:
__name__=?模塊名
作用:用來控制.py文件在不同的應用場景下執行不同的邏輯
if __name__ == '__main__':
def fib(n): a, b = 0, 1while b < n:print(b, end=' ')a, b = b, a+bprint()if __name__ == "__main__":print(__name__)num = input('num :')fib(int(num))View Code
?
二 包
包是一種通過使用‘.模塊名’來組織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/__init__.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)文件內容
?
2.1 注意事項
1.關于包相關的導入語句也分為import和from ... import ...兩種,但是無論哪種,無論在什么位置,在導入時都必須遵循一個原則:凡是在導入時帶點的,點的左邊都必須是一個包,否則非法。可以帶有一連串的點,如item.subitem.subsubitem,但都必須遵循這個原則。
2.對于導入后,在使用時就沒有這種限制了,點的左邊可以是包,模塊,函數,類(它們都可以用點的方式調用自己的屬性)。
3.對比import item 和from item import name的應用場景:
如果我們想直接使用name那必須使用后者。
2.2 import?
我們在與包glance同級別的文件中測試
1 import glance.db.models
2 glance.db.models.register_models('mysql')?    2.3 from ... import ...
需要注意的是from后import導入的模塊,必須是明確的一個不能帶點,否則會有語法錯誤,如:from a import b.c是錯誤語法
我們在與包glance同級別的文件中測試?
1 from glance.db import models
2 models.register_models('mysql')
3 
4 from glance.db.models import register_models
5 register_models('mysql')    2.4 __init__.py文件
不管是哪種方式,只要是第一次導入包或者是包的任何其他部分,都會依次執行包下的__init__.py文件(我們可以在每個包的文件內都打印一行內容來驗證一下),這個文件可以為空,但是也可以存放一些初始化包的代碼。
2.5 ?from glance.api import *
在講模塊時,我們已經討論過了從一個模塊內導入所有*,此處我們研究從一個包導入所有*。
此處是想從包api中導入所有,實際上該語句只會導入包api下__init__.py文件中定義的名字,我們可以在這個文件中定義__all___:
#在__init__.py中定義
x=10def func():print('from api.__init.py')__all__=['x','func','policy']    ?此時我們在于glance同級的文件中執行from glance.api import *就導入__all__中的內容(versions仍然不能導入)。
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.pyfrom glance.api import * policy.get()
#=============>bin目錄:存放執行腳本 #start.py import sys,osBASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR)from core import core from conf import my_log_settingsif __name__ == '__main__':my_log_settings.load_my_logging_cfg()core.run()#=============>conf目錄:存放配置文件 #config.ini [DEFAULT] user_timeout = 1000[egon] password = 123 money = 10000000[alex] password = alex3714 money=10000000000[yuanhao] password = ysb123 money=10#settings.py import os config_path=r'%s\%s' %(os.path.dirname(os.path.abspath(__file__)),'config.ini') user_timeout=10 user_db_path=r'%s\%s' %(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),\'db')#my_log_settings.py """ logging配置 """import os import logging.config# 定義三種日志輸出格式 開始 standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \'[%(levelname)s][%(message)s]' #其中name為getlogger指定的名字 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'# 定義日志輸出格式 結束 logfile_dir = r'%s\log' %os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # log文件的目錄 logfile_name = 'all2.log' # log文件名# 如果不存在定義的日志目錄就創建一個 if not os.path.isdir(logfile_dir):os.mkdir(logfile_dir)# log文件的全路徑 logfile_path = os.path.join(logfile_dir, logfile_name)# log配置字典 LOGGING_DIC = {'version': 1,'disable_existing_loggers': False,'formatters': {'standard': {'format': standard_format},'simple': {'format': simple_format},},'filters': {},'handlers': {#打印到終端的日志'console': {'level': 'DEBUG','class': 'logging.StreamHandler', # 打印到屏幕'formatter': 'simple'},#打印到文件的日志,收集info及以上的日志'default': {'level': 'DEBUG','class': 'logging.handlers.RotatingFileHandler', # 保存到文件'formatter': 'standard','filename': logfile_path, # 日志文件'maxBytes': 1024*1024*5, # 日志大小 5M'backupCount': 5,'encoding': 'utf-8', # 日志文件的編碼,再也不用擔心中文log亂碼了 },},'loggers': {#logging.getLogger(__name__)拿到的logger配置'': {'handlers': ['default', 'console'], # 這里把上面定義的兩個handler都加上,即log數據既寫入文件又打印到屏幕'level': 'DEBUG','propagate': True, # 向上(更高level的logger)傳遞 },}, }def load_my_logging_cfg():logging.config.dictConfig(LOGGING_DIC) # 導入上面定義的logging配置logger = logging.getLogger(__name__) # 生成一個log實例logger.info('It works!') # 記錄該文件的運行狀態if __name__ == '__main__':load_my_logging_cfg()#=============>core目錄:存放核心邏輯 #core.py import logging import time from conf import settings from lib import read_iniconfig=read_ini.read(settings.config_path) logger=logging.getLogger(__name__)current_user={'user':None,'login_time':None,'timeout':int(settings.user_timeout)} def auth(func):def wrapper(*args,**kwargs):if current_user['user']:interval=time.time()-current_user['login_time']if interval < current_user['timeout']:return func(*args,**kwargs)name = input('name>>: ')password = input('password>>: ')if config.has_section(name):if password == config.get(name,'password'):logger.info('登錄成功')current_user['user']=namecurrent_user['login_time']=time.time()return func(*args,**kwargs)else:logger.error('用戶名不存在')return wrapper@auth def buy():print('buy...')@auth def run():print(''' 購物 查看余額 轉賬''')while True:choice = input('>>: ').strip()if not choice:continueif choice == '1':buy()if __name__ == '__main__':run()#=============>db目錄:存放數據庫文件 #alex_json #egon_json#=============>lib目錄:存放自定義的模塊與包 #read_ini.py import configparser def read(config_file):config=configparser.ConfigParser()config.read(config_file)return config#=============>log目錄:存放日志 #all2.log [2017-07-29 00:31:40,272][MainThread:11692][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!] [2017-07-29 00:31:41,789][MainThread:11692][task_id:core.core][core.py:25][ERROR][用戶名不存在] [2017-07-29 00:31:46,394][MainThread:12348][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!] [2017-07-29 00:31:47,629][MainThread:12348][task_id:core.core][core.py:25][ERROR][用戶名不存在] [2017-07-29 00:31:57,912][MainThread:10528][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!] [2017-07-29 00:32:03,340][MainThread:12744][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!] [2017-07-29 00:32:05,065][MainThread:12916][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!] [2017-07-29 00:32:08,181][MainThread:12916][task_id:core.core][core.py:25][ERROR][用戶名不存在] [2017-07-29 00:32:13,638][MainThread:7220][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!] [2017-07-29 00:32:23,005][MainThread:7220][task_id:core.core][core.py:20][INFO][登錄成功] [2017-07-29 00:32:40,941][MainThread:7220][task_id:core.core][core.py:20][INFO][登錄成功] [2017-07-29 00:32:47,222][MainThread:7220][task_id:core.core][core.py:20][INFO][登錄成功] [2017-07-29 00:32:51,949][MainThread:7220][task_id:core.core][core.py:25][ERROR][用戶名不存在] [2017-07-29 00:33:00,213][MainThread:7220][task_id:core.core][core.py:20][INFO][登錄成功] [2017-07-29 00:33:50,118][MainThread:8500][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!] [2017-07-29 00:33:55,845][MainThread:8500][task_id:core.core][core.py:20][INFO][登錄成功] [2017-07-29 00:34:06,837][MainThread:8500][task_id:core.core][core.py:25][ERROR][用戶名不存在] [2017-07-29 00:34:09,405][MainThread:8500][task_id:core.core][core.py:25][ERROR][用戶名不存在] [2017-07-29 00:34:10,645][MainThread:8500][task_id:core.core][core.py:25][ERROR][用戶名不存在]View Code
?
?
?
轉載于:https://www.cnblogs.com/bzluren/p/10680274.html
總結
                            
                        - 上一篇: 面包和油酥饼哪个热量高
 - 下一篇: Loadrunner安装使用入门