1. 程式人生 > >python--模塊用法和包

python--模塊用法和包

找到 directory ... error isp input continue insert 永久

1 什麽是模塊?

模塊概念:

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

但其實import加載的模塊分為四個通用類別: 

  1 使用python編寫的代碼(.py文件)

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

  3 包好一組模塊的包

  4 使用C編寫並鏈接到python解釋器的內置模塊

2 為何要使用模塊?

如果你退出python解釋器然後重新進入,那麽你之前定義的函數或者變量都將丟失,因此我們通常將程序寫到文件中以便永久保存下來,需要時就通過python test.py方式去執行,此時test.py被稱為腳本script。

隨著程序的發展,功能越來越多,為了方便管理,我們通常將程序分成一個個的文件,這樣做程序的結構更清晰,方便管理。這時我們不僅僅可以把這些文件當做腳本去執行,還可以把他們當做模塊來導入到其他的模塊中,實現了功能的重復利用,

3.如何使用模塊
3.1 import

示例文件:自定義模塊my_module.py,文件名my_module.py,模塊名my_module

#my_module.py
print(from the my_module.py)

money=1000

def read1():
    print(my_module->read1->money,money)

def read2():
    print(my_module->read2 calling read1)
    read1()

def change():
    global money
    money=0
模塊可以包含可執行的語句和函數的定義,這些語句的目的是初始化模塊,它們只在模塊名第一次遇到導入import語句時才執行(import語句是可以在程序中的任意位置使用的,且針對同一個模塊很import多次,為了防止你重復導入,python的優化手段是:第一次導入後就將模塊名加載到內存了,後續的import語句僅是對已經加載大內存中的模塊對象增加了一次引用,不會重新執行模塊內的語句)
#demo.py
import my_module #只在第一次導入時才執行my_module.py內代碼,此處的顯式效果是只打印一次‘from the my_module.py‘,當然其他的頂級代碼也都被執行了,只不過沒有顯示效果.
import my_module
import my_module
import my_module

‘‘‘
執行結果:
from the my_module.py
‘‘‘

我們可以從sys.modules中找到當前已經加載的模塊,sys.modules是一個字典,內部包含模塊名與模塊對象的映射,該字典決定了導入模塊時是否需要重新導入。

  每個模塊都是一個獨立的名稱空間,定義在這個模塊中的函數,把這個模塊的名稱空間當做全局名稱空間,這樣我們在編寫自己的模塊時,就不用擔心我們定義在自己模塊中全局變量會在被導入時,與使用者的全局變量沖突

  

#測試一:money與my_module.money不沖突
#demo.py
import my_module
money=10
print(my_module.money)

‘‘‘
執行結果:
from the my_module.py
1000
‘‘‘

#測試二:read1與my_module.read1不沖突

#demo.py

import my_module
def read1():
    print(========)
my_module.read1()

‘‘‘
執行結果:
from the my_module.py
my_module->read1->money 1000
‘‘‘
#測試三:執行my_module.change()操作的全局變量money仍然是my_module中的
#demo.py
import my_module
money=1
my_module.change()
print(money)

‘‘‘
執行結果:
from the my_module.py
1
‘‘‘

總結:首次導入模塊my_module時會做三件事:

1.為源文件(my_module模塊)創建新的名稱空間,在my_module中定義的函數和方法若是使用到了global時訪問的就是這個名稱空間。

2.在新創建的命名空間中執行模塊中包含的代碼,見初始導入import my_module

1 提示:導入模塊時到底執行了什麽?
2 
3 In fact function definitions are also ‘statements’ that are ‘executed’; the execution of a module-level function definition enters the function name in the module’s global symbol table.
4 事實上函數定義也是“被執行”的語句,模塊級別函數定義的執行將函數名放入模塊全局名稱空間表,用globals()可以查看

3.創建名字my_module來引用該命名空間

1 這個名字和變量名沒什麽區別,都是‘第一類的’,且使用my_module.名字的方式可以訪問my_module.py文件中定義的名字,my_module.名字與test.py中的名字來自兩個完全不同的地方。

為模塊名起別名,相當於m1=1;m2=m1

1 import my_module as sm
2 print(sm.money)

示範用法一:

有兩中sql模塊mysql和oracle,根據用戶的輸入,選擇不同的sql功能

#mysql.py
def sqlparse():
    print(from mysql sqlparse)
#oracle.py
def sqlparse():
    print(from oracle sqlparse)

#test.py
db_type=input(>>: )
if db_type == mysql:
    import mysql as db
elif db_type == oracle:
    import oracle as db

db.sqlparse() 
復制代碼

示範用法二:

為已經導入的模塊起別名的方式對編寫可擴展的代碼很有用,假設有兩個模塊xmlreader.py和csvreader.py,它們都定義了函數read_data(filename):用來從文件中讀取一些數據,但采用不同的輸入格式。可以編寫代碼來選擇性地挑選讀取模塊,例如

if file_format == xml:
     import xmlreader as reader
elif file_format == csv:
     import csvreader as reader
data=reader.read_date(filename)

在一行導入多個模塊



1 import sys,os,re
 3.2 from ... import...
3.2.1

對比import my_module,會將源文件的名稱空間‘my_module‘帶到當前名稱空間中,使用時必須是my_module.名字的方式


而from 語句相當於import,也會創建新的名稱空間,但是將my_module中的名字直接導入到當前的名稱空間中,在當前名稱空間中,直接使用名字就可以了、



 1 from my_module import read1,read2

這樣在當前位置直接使用read1和read2就好了,執行時,仍然以my_module.py文件全局名稱空間



#測試一:導入的函數read1,執行時仍然回到my_module.py中尋找全局變量money
#demo.py
from my_module import read1
money=1000
read1()
‘‘‘
執行結果:
from the my_module.py
spam->read1->money 1000
‘‘‘

#測試二:導入的函數read2,執行時需要調用read1(),仍然回到my_module.py中找read1()
#demo.py
from my_module import read2
def read1():
    print(==========)
read2()

‘‘‘
執行結果:
from the my_module.py
my_module->read2 calling read1
my_module->read1->money 1000
‘‘‘


如果當前有重名read1或者read2,那麽會有覆蓋效果。



#測試三:導入的函數read1,被當前位置定義的read1覆蓋掉了
#demo.py
from my_module import read1
def read1():
    print(==========)
read1()
‘‘‘
執行結果:
from the my_module.py
==========
‘‘‘


需要特別強調的一點是:python中的變量賦值不是一種存儲操作,而只是一種綁定關系,如下:



from my_module import money,read1
money=100 #將當前位置的名字money綁定到了100
print(money) #打印當前的名字
read1() #讀取my_module.py中的名字money,仍然為1000

‘‘‘
from the my_module.py
100
my_module->read1->money 1000
‘‘‘

也支持as

可以給模塊起別名



1 from my_module import read1 as read
 

也支持導入多行



1 from my_module import (read1,
2                   read2,
3                   money)

from my_module import * 把my_module中所有的不是以下劃線(_)開頭的名字都導入到當前位置,大部分情況下我們的python程序不應該使用這種導入方式,因為*你不知道你導入什麽名字,很有可能會覆蓋掉你之前已經定義的名字。而且可讀性極其的差,在交互式環境中導入時沒有問題。


from my_module import * #將模塊my_module中所有的名字都導入到當前名稱空間
print(money)
print(read1)
print(read2)
print(change)

‘‘‘
執行結果:
from the my_module.py
1000
<function read1 at 0x1012e8158>
<function read2 at 0x1012e81e0>
<function change at 0x1012e8268>
‘‘‘

在my_module.py中新增一行

__all__=[money‘,read1‘] #這樣在另外一個文件中用from my_module import *就這能導入列表中規定的兩個名字

*如果my_module.py中的名字前加_,即_money,則from my_module import *,則_money不能被導入

考慮到性能的原因,每個模塊只被導入一次,放入字典sys.modules中,如果你改變了模塊的內容,你必須重啟程序,python不支持重新加載或卸載之前導入的模塊,

有的同學可能會想到直接從sys.modules中刪除一個模塊不就可以卸載了嗎,註意了,你刪了sys.modules中的模塊對象仍然可能被其他程序的組件所引用,因而不會被清除。

特別的對於我們引用了這個模塊中的一個類,用這個類產生了很多對象,因而這些對象都有關於這個模塊的引用。

如果只是你想交互測試的一個模塊,使用 importlib.reload(), e.g. import importlib; importlib.reload(modulename),這只能用於測試環境。


def func1():
    print(func1‘)

import time,importlib
import aa
 
time.sleep(20)
# importlib.reload(aa)
aa.func1()

在20秒的等待時間裏,修改aa.py中func1的內容,等待test.py的結果。

打開importlib註釋,重新測試

我們可以通過模塊的全局變量__name__來查看模塊名:
當做腳本運行:
__name__ 等於‘__main__‘

當做模塊導入:
__name__= 模塊名

作用:用來控制.py文件在不同的應用場景下執行不同的邏輯
if __name__ == ‘__main__‘:

def fib(n):   
    a, b = 0, 1
    while b < n:
        print(b, end=)
        a, b = b, a+b
    print()

if __name__ == "__main__":
    print(__name__)
    num = input(num :)
    fib(int(num))

3.4 模塊搜索路徑

python解釋器在啟動時會自動加載一些模塊,可以使用sys.modules查看

在第一次導入某個模塊時(比如my_module),會先檢查該模塊是否已經被加載到內存中(當前執行文件的名稱空間對應的內存),如果有則直接引用

如果沒有,解釋器則會查找同名的內建模塊,如果還沒有找到就從sys.path給出的目錄列表中依次尋找my_module.py文件。

所以總結模塊的查找順序是:內存中已經加載的模塊->內置模塊->sys.path路徑中包含的模塊

sys.path的初始化的值來自於:

The directory containing the input script (or the current directory when no file is specified).
PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).
The installation-dependent default.

需要特別註意的是:我們自定義的模塊名不應該與系統內置模塊重名。雖然每次都說,但是仍然會有人不停的犯錯。

在初始化後,python程序可以修改sys.path,路徑放到前面的優先於標準庫被加載。

1 >>> import sys
2 >>> sys.path.append(/a/b/c/d)
3 >>> sys.path.insert(0,/x/y/z‘) #排在前的目錄,優先被搜索

註意:搜索時按照sys.path中從左到右的順序查找,位於前的優先被查找,sys.path中還可能包含.zip歸檔文件和.egg文件,python會把.zip歸檔文件當成一個目錄去處理。


#首先制作歸檔文件:zip module.zip foo.py bar.py

import sys
sys.path.append(module.zip)
import foo,bar

#也可以使用zip中目錄結構的具體位置
sys.path.append(module.zip/lib/python)

#windows下的路徑不加r開頭,會語法錯誤
sys.path.insert(0,rC:\Users\Administrator\PycharmProjects\a‘)

至於.egg文件是由setuptools創建的包,這是按照第三方python庫和擴展時使用的一種常見格式,.egg文件實際上只是添加了額外元數據(如版本號,依賴項等)的.zip文件。

需要強調的一點是:只能從.zip文件中導入.py,.pyc等文件。使用C編寫的共享庫和擴展塊無法直接從.zip文件中加載(此時setuptools等打包系統有時能提供一種規避方法),且從.zip中加載文件不會創建.pyc或者.pyo文件,因此一定要事先創建他們,來避免加載模塊是性能下降。

二 包


執行文件為test.py,內容
#test.py
import aaa
同級目錄下創建目錄aaa,然後自建空__init__.py(或者幹脆建包)
需求:驗證導入包就是在導入包下的__init__.py
    先執行看結果
    再在__init__.py添加打印信息後,重新執行
需求:
aaa.x
aaa.y
解決:在__init__.py中定義名字x和y
在aaa下建立m1.py和m2.py
#m1.py
def f1():
    print(from 1)
#m2.py
def f2():
    print(from 2)
需求:
aaa.m1 #進而aaa.m1.func1()
aaa.m2 #進而aaa.m2.func2()

解決:在__init__.py中定義名字m1和m2,先定義一個普通變量,再引出如何導入模塊名
在aaa下新建包bbb
需求:
aaa.bbb

解決在aaa的__init__.py內導入名字bbb
在bbb下建立模塊m3.py
#m3.py
def f3():
    print(from 3)
需求:
aaa.bbb.m3 #進而aaa.bbb.m3.f3()

解決:是bbb下的名字m3,因而要在bbb的__init__.py文件中導入名字m3
絕對導入變成相對導入
需求:
aaa.m1()
aaa.m2()
aaa.m3()

解決:在aaa的__init__.py中拿到名字m1、m2、m3
包內模塊直接的相對導入,強調包的本質:包內的模塊是用來被導入的,而不是被執行的
用戶無法區分模塊是文件還是一個包,我們定義包是為了方便開發者維護
將包整理當做一個模塊,移動到別的目錄下,操作sys.path

Packages are a way of structuring Python’s module namespace by using “dotted module names”

包是一種通過使用‘.模塊名’來組織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)
2.2 import

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

1 import glance.db.models
2 glance.db.models.register_models

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=10

def 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.py



from glance.api import *
policy.get()

2.6 絕對導入和相對導入

我們的最頂級包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同級的文件中測試

1 from glance.api import versions 

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

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

比如我們想在glance/api/versions.py中導入glance/api/policy.py,有的同學一抽這倆模塊是在同一個目錄下,十分開心的就去做了,它直接這麽做

1 #在version.py中
2 
3 import policy
4 policy.get()

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

但是你想啊,你子包中的模塊version.py極有可能是被一個glance包同一級別的其他文件導入,比如我們在於glance同級下的一個test.py文件中導入version.py,如下

from glance.api import versions

‘‘‘
執行結果:
ImportError: No module named ‘policy‘
‘‘‘

‘‘‘
分析:
此時我們導入versions在versions.py中執行
import policy需要找從sys.path也就是從當前目錄找policy.py,
這必然是找不到的
‘‘‘

glance/                   

├── __init__.py      from glance import api
                             from glance import cmd
                             from glance import db

├── api                  

│   ├── __init__.py  from glance.api import policy
                              from glance.api import versions

│   ├── policy.py

│   └── versions.py

├── cmd                 from glance.cmd import manage

│   ├── __init__.py

│   └── manage.py

└── db                   from glance.db import models

    ├── __init__.py

    └── models.py

glance/                   

├── __init__.py      from . import api  #.表示當前目錄
                     from . import cmd
                     from . import db

├── api                  

│   ├── __init__.py  from . import policy
                     from . import versions

│   ├── policy.py

│   └── versions.py

├── cmd              from . import manage

│   ├── __init__.py

│   └── manage.py    from ..api import policy   
                     #..表示上一級目錄,想再manage中使用policy中的方法就需要回到上一級glance目錄往下找api包,從api導入policy

└── db               from . import models

    ├── __init__.py

    └── models.py

2.7 單獨導入包

單獨導入包名稱時不會導入包中所有包含的所有子模塊,如

#在與glance同級的test.py中
import glance
glance.cmd.manage.main()

‘‘‘
執行結果:
AttributeError: module ‘glance‘ has no attribute ‘cmd‘

‘‘‘

解決方法:

1 #glance/__init__.py
2 from . import cmd
3 
4 #glance/cmd/__init__.py
5 from . import manage

執行:

1 #在於glance同級的test.py中
2 import glance
3 glance.cmd.manage.main()

千萬別問:__all__不能解決嗎,__all__是用於控制from...import *

import glance之後直接調用模塊中的方法

glance/                   

├── __init__.py     from .api import *
                    from .cmd import *
                    from .db import *    
├── api                  

│   ├── __init__.py   __all__ = [policy‘,versions] 

│   ├── policy.py

│   └── versions.py

├── cmd               __all__ = [manage]    

│   ├── __init__.py

│   └── manage.py    

└── db                __all__ = [models]              

    ├── __init__.py

    └── models.py


import glance
policy.get()

軟件開發規範

技術分享

#=============>bin目錄:存放執行腳本
#start.py
import sys,os

BASE_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_settings

if __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_ini

config=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‘]=name
current_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:continue
if 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][用戶名不存在]

python--模塊用法和包