模塊與包

一 模塊介紹

1、什么是模塊?

#常見的場景:一個模塊就是一個包含了一組功能的python文件,比如spam.py,模塊名為spam,可以通過import spam使用。#在python中,模塊的使用方式都是一樣的,但其實細說的話,模塊可以分為四個通用類別: 
使用python編寫的.py文件
已被編譯為共享庫或DLL的C或C++擴展
把一系列模塊組織到一起的文件夾(注:文件夾下有一個__init__.py文件,該文件夾稱之為包)
使用C編寫并鏈接到python解釋器的內置模塊

2、為何要使用模塊?

#1、從文件級別組織程序,更方便管理
隨著程序的發展,功能越來越多,為了方便管理,我們通常將程序分成一個個的文件,這樣做程序的結構更清晰,方便管理。這時我們不僅僅可以把這些文件當做腳本去執行,還可以把他們當做模塊來導入到其他的模塊中,實現了功能的重復利用#2、拿來主義,提升開發效率
同樣的原理,我們也可以下載別人寫好的模塊然后導入到自己的項目中使用,這種拿來主義,可以極大地提升我們的開發效率#ps:
如果你退出python解釋器然后重新進入,那么你之前定義的函數或者變量都將丟失,因此我們通常將程序寫到文件中以便永久保存下來,需要時就通過python test.py方式去執行,此時test.py被稱為腳本script。

3、以spam.py為例來介紹模塊的使用:文件名spam.py,模塊名spam

#spam.py
print('from the spam.py')money=1000def read1():print('spam模塊:',money)def read2():print('spam模塊')read1()def change():global moneymoney=0
spam.py

二 使用模塊之import

1、import的使用

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

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

2、在第一次導入模塊時會做三件事,重復導入會直接引用內存中已經加載好的結果

復制代碼
#1.為源文件(spam模塊)創建新的名稱空間,在spam中定義的函數和方法若是使用到了global時訪問的就是這個名稱空間。#2.在新創建的命名空間中執行模塊中包含的代碼,見初始導入import spam提示:導入模塊時到底執行了什么?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.事實上函數定義也是“被執行”的語句,模塊級別函數定義的執行將函數名放入模塊全局名稱空間表,用globals()可以查看#3.創建名字spam來引用該命名空間這個名字和變量名沒什么區別,都是‘第一類的’,且使用spam.名字的方式可以訪問spam.py文件中定義的名字,spam.名字與test.py中的名字來自兩個完全不同的地方。
復制代碼

3、被導入模塊有獨立的名稱空間

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

復制代碼
#test.py
import spam 
money=10
print(spam.money)'''
執行結果:
from the spam.py
1000
'''
復制代碼
測試一:money與spam.money不沖突
#test.py
import spam
def read1():print('========')
spam.read1()'''
執行結果:
from the spam.py
spam->read1->money 1000
'''測試二:read1與spam.read1不沖突
測試二:read1與spam.read1不沖突
#test.py
import spam
money=1
spam.change()
print(money)'''
執行結果:
from the spam.py
'''測試三:執行spam.change()操作的全局變量money仍然是spam中的
測試三:執行spam.change()操作的全局變量money仍然是spam中的

4、為模塊名起別名

為已經導入的模塊起別名的方式對編寫可擴展的代碼很有用

1 import spam 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 dbdb.sqlparse()
View Code

假設有兩個模塊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)
View Code

5、在一行導入多個模塊

1 import sys,os,re

三 使用模塊之from ... import...

1、from...import...的使用

 1 from spam import read1,read2

2、from...import 與import的對比

#唯一的區別就是:使用from...import...則是將spam中的名字直接導入到當前的名稱空間中,所以在當前名稱空間中,直接使用名字就可以了、無需加前綴:spam.#from...import...的方式有好處也有壞處好處:使用起來方便了壞處:容易與當前執行文件中的名字沖突

驗證一:當前位置直接使用read1和read2就好了,執行時,仍然以spam.py文件全局名稱空間

#測試一:導入的函數read1,執行時仍然回到spam.py中尋找全局變量money
#test.py
from spam import read1
money=1000
read1()
'''
執行結果:
from the spam.py
spam->read1->money 1000
'''#測試二:導入的函數read2,執行時需要調用read1(),仍然回到spam.py中找read1()
#test.py
from spam import read2
def read1():print('==========')
read2()'''
執行結果:
from the spam.py
spam->read2 calling read
spam->read1->money 1000
'''
View Code

驗證二:如果當前有重名read1或者read2,那么會有覆蓋效果。

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

驗證三:導入的方法在執行時,始終是以源文件為準的

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

3、也支持as

1 from spam import read1 as read

4、一行導入多個名字

from spam import read1,read2,money

5、from...import *

#from spam import * 把spam中所有的不是以下劃線(_)開頭的名字都導入到當前位置#大部分情況下我們的python程序不應該使用這種導入方式,因為*你不知道你導入什么名字,很有可能會覆蓋掉你之前已經定義的名字。而且可讀性極其的差,在交互式環境中導入時沒有問題。
from spam import * #將模塊spam中所有的名字都導入到當前名稱空間
print(money)
print(read1)
print(read2)
print(change)'''
執行結果:
from the spam.py
<function read1 at 0x1012e8158>
<function read2 at 0x1012e81e0>
<function change at 0x1012e8268>
'''
View Code

可以使用__all__來控制*(用來發布新版本),在spam.py中新增一行

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

四 模塊的重載 (了解)

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

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

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

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

def func1():print('func1')
aa.py的初始內容
1 import time,importlib
2 import aa
3 
4 time.sleep(20)
5 # importlib.reload(aa)
6 aa.func1()
執行test.py

五 py文件區分兩種用途:模塊與腳本

#編寫好的一個python文件可以有兩種用途:
一:腳本,一個文件就是整個程序,用來被執行
二:模塊,文件中存放著一堆功能,用來被導入使用


#python為我們內置了全局變量__name__,
當文件被當做腳本執行時:__name__ 等于'__main__'
當文件被當做模塊導入時:__name__等于模塊名

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

#fib.pydef fib(n):    # write Fibonacci series up to na, b = 0, 1while b < n:print(b, end=' ')a, b = b, a+bprint()def fib2(n):   # return Fibonacci series up to nresult = []a, b = 0, 1while b < n:result.append(b)a, b = b, a+breturn resultif __name__ == "__main__":import sysfib(int(sys.argv[1]))#執行:python fib.py <arguments>
python fib.py 50 #在命令行
View Code

六 模塊搜索路徑

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

#官網鏈接:https://docs.python.org/3/tutorial/modules.html#the-module-search-path
搜索路徑:
當一個命名為spam的模塊被導入時解釋器首先會從內建模塊中尋找該名字找不到,則去sys.path中找該名字sys.path從以下位置初始化
執行文件所在的當前目錄
PTYHONPATH(包含一系列目錄名,與shell變量PATH語法一樣)
依賴安裝時默認指定的注意:在支持軟連接的文件系統中,執行腳本所在的目錄是在軟連接之后被計算的,換句話說,包含軟連接的目錄不會被添加到模塊的搜索路徑中在初始化后,我們也可以在python程序中修改sys.path,執行文件所在的路徑默認是sys.path的第一個目錄,在所有標準庫路徑的前面。這意味著,當前目錄是優先于標準庫目錄的,需要強調的是:我們自定義的模塊名不要跟python標準庫的模塊名重復,除非你是故意的,傻叉。
詳細的

七 編譯python文件(了解)

為了提高加載模塊的速度,強調強調強調:提高的是加載速度而絕非運行速度。python解釋器會在__pycache__目錄中下緩存每個模塊編譯后的版本,格式為:module.version.pyc。通常會包含python的版本號。例如,在CPython3.3版本下,spam.py模塊會被緩存成__pycache__/spam.cpython-33.pyc。這種命名規范保證了編譯后的結果多版本共存。

Python檢查源文件的修改時間與編譯的版本進行對比,如果過期就需要重新編譯。這是完全自動的過程。并且編譯的模塊是平臺獨立的,所以相同的庫可以在不同的架構的系統之間共享,即pyc使一種跨平臺的字節碼,類似于JAVA火.NET,是由python虛擬機來執行的,但是pyc的內容跟python的版本相關,不同的版本編譯后的pyc文件不同,2.5編譯的pyc文件不能到3.5上執行,并且pyc文件是可以反編譯的,因而它的出現僅僅是用來提升模塊的加載速度的,不是用來加密的。

#python解釋器在以下兩種情況下不檢測緩存
#1 如果是在命令行中被直接導入模塊,則按照這種方式,每次導入都會重新編譯,并且不會存儲編譯后的結果(python3.3以前的版本應該是這樣)python -m spam.py#2 如果源文件不存在,那么緩存的結果也不會被使用,如果想在沒有源文件的情況下來使用編譯后的結果,則編譯后的結果必須在源目錄下
sh-3.2# ls
__pycache__ spam.py
sh-3.2# rm -rf spam.py 
sh-3.2# mv __pycache__/spam.cpython-36.pyc ./spam.pyc
sh-3.2# python3 spam.pyc 
spam#提示:
1.模塊名區分大小寫,foo.py與FOO.py代表的是兩個模塊
2.你可以使用-O或者-OO轉換python命令來減少編譯模塊的大小-O轉換會幫你去掉assert語句-OO轉換會幫你去掉assert語句和__doc__文檔字符串由于一些程序可能依賴于assert語句或文檔字符串,你應該在在確認需要的情況下使用這些選項。
3.在速度上從.pyc文件中讀指令來執行不會比從.py文件中讀指令執行更快,只有在模塊被加載時,.pyc文件才是更快的4.只有使用import語句是才將文件自動編譯為.pyc文件,在命令行或標準輸入中指定運行腳本則不會生成這類文件,因而我們可以使用compieall模塊為一個目錄中的所有模塊創建.pyc文件模塊可以作為一個腳本(使用python -m compileall)編譯Python源  
python -m compileall /module_directory 遞歸著編譯
如果使用python -O -m compileall /module_directory -l則只一層命令行里使用compile()函數時,自動使用python -O -m compileall詳見:https://docs.python.org/3/library/compileall.html#module-compileall

詳細的
詳細的

八 包介紹

1、什么是包?

#官網解釋
Packages are a way of structuring Python’s module namespace by using “dotted module names”
包是一種通過使用‘.模塊名’來組織python模塊名稱空間的方式。#具體的:包就是一個包含有__init__.py文件的文件夾,所以其實我們創建包的目的就是為了用文件夾將文件/模塊組織起來#需要強調的是:1. 在python3中,即使包下沒有__init__.py文件,import 包仍然不會報錯,而在python2中,包下一定要有該文件,否則import 包報錯2. 創建包的目的不是為了運行,而是被導入使用,記住,包只是模塊的一種形式而已,包的本質就是一種模塊

3、注意事項

復制代碼
#1.關于包相關的導入語句也分為import和from ... import ...兩種,但是無論哪種,無論在什么位置,在導入時都必須遵循一個原則:凡是在導入時帶點的,點的左邊都必須是一個包,否則非法。可以帶有一連串的點,如item.subitem.subsubitem,但都必須遵循這個原則。但對于導入后,在使用時就沒有這種限制了,點的左邊可以是包,模塊,函數,類(它們都可以用點的方式調用自己的屬性)。#2、import導入文件時,產生名稱空間中的名字來源于文件,import 包,產生的名稱空間的名字同樣來源于文件,即包下的__init__.py,導入包本質就是在導入該文件#3、包A和包B下有同名模塊也不會沖突,如A.a與B.a來自倆個命名空間
復制代碼

4、上課流程

實驗一準備:執行文件為test.py,內容#test.pyimport aaa同級目錄下創建目錄aaa,然后自建空__init__.py(或者干脆建包)需求:驗證導入包就是在導入包下的__init__.py解決:先執行看結果再在__init__.py添加打印信息后,重新執行2、實驗二準備:基于上面的結果需求:aaa.xaaa.y解決:在__init__.py中定義名字x和y3、實驗三準備:在aaa下建立m1.py和m2.py#m1.pydef f1():print('from 1')#m2.pydef f2():print('from 2')需求:aaa.m1 #進而aaa.m1.func1()aaa.m2 #進而aaa.m2.func2()
解決:在__init__.py中定義名字m1和m2,先定義一個普通變量,再引出如何導入模塊名,強調:環境變量是以執行文件為準4、實驗四準備:在aaa下新建包bbb需求:aaa.bbb解決:在aaa的__init__.py內導入名字bbb5、實驗五準備:在bbb下建立模塊m3.py#m3.pydef f3():print('from 3')需求:aaa.bbb.m3 #進而aaa.bbb.m3.f3()
解決:是bbb下的名字m3,因而要在bbb的__init__.py文件中導入名字m3,from aaa.bbb import m36、實驗六準備:基于上面的結果需求:aaa.m1()aaa.m2()aaa.m3()進而實現aaa.f1()aaa.f2()aaa.f3()先用絕對導入,再用相對導入解決:在aaa的__init__.py中拿到名字m1、m2、m3包內模塊直接的相對導入,強調包的本質:包內的模塊是用來被導入的,而不是被執行的用戶無法區分模塊是文件還是一個包,我們定義包是為了方便開發者維護7、實驗七將包整理當做一個模塊,移動到別的目錄下,操作sys.path
View Code

九 包的使用

1、示范文件

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、包的使用之import?

1 import glance.db.models
2 glance.db.models.register_models('mysql')?

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

復制代碼
#在與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()

3、包的使用之from ... import ...

需要注意的是from后import導入的模塊,必須是明確的一個不能帶點,否則會有語法錯誤,如:from a import b.c是錯誤語法

1 from glance.db import models
2 models.register_models('mysql')
3 
4 from glance.db.models import register_models
5 register_models('mysql')

4、from glance.api import *

在講模塊時,我們已經討論過了從一個模塊內導入所有*,此處我們研究從一個包導入所有*。

此處是想從包api中導入所有,實際上該語句只會導入包api下__init__.py文件中定義的名字,我們可以在這個文件中定義__all___:

復制代碼
1 #在__init__.py中定義
2 x=10
3 
4 def func():
5     print('from api.__init.py')
6 
7 __all__=['x','func','policy']
復制代碼

此時我們在于glance同級的文件中執行from glance.api import *就導入__all__中的內容(versions仍然不能導入)。

練習:

#執行文件中的使用效果如下,請處理好包的導入
from glance import *get()
create_resource('a.conf')
main()
register_models('mysql')
#在glance.__init__.py中
from .api.policy import get
from .api.versions import create_resourcefrom .cmd.manage import main
from .db.models import  register_models__all__=['get','create_resource','main','register_models']
View Code

5、絕對導入和相對導入

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

絕對導入:以glance作為起始

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

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

復制代碼
1 在glance/api/version.py
2 
3 #絕對導入
4 from glance.cmd import manage
5 manage.main()
6 
7 #相對導入
8 from ..cmd import manage
9 manage.main()
復制代碼

測試結果:注意一定要在于glance同級的文件中測試

1 from glance.api import versions?

6、包以及包所包含的模塊都是用來被導入的,而不是被直接執行的。而環境變量都是以執行文件為準的

比如我們想在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,如下

復制代碼
 1 from glance.api import versions2 3 '''4 執行結果:5 ImportError: No module named 'policy'6 '''7 8 '''9 分析:
10 此時我們導入versions在versions.py中執行
11 import policy需要找從sys.path也就是從當前目錄找policy.py,
12 這必然是找不到的
13 '''
復制代碼

7、包的分發(了解)

https://packaging.python.org/distributing/

十 軟件開發規范

#===============>star.py
import sys,os
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)from core import srcif __name__ == '__main__':src.run()
#===============>settings.py
import osBASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DB_PATH=os.path.join(BASE_DIR,'db','db.json')
LOG_PATH=os.path.join(BASE_DIR,'log','access.log')
LOGIN_TIMEOUT=5"""
logging配置
"""
# 定義三種日志輸出格式
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'# 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': LOG_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)傳遞
        },},
}#===============>src.py
from conf import settings
from lib import common
import timelogger=common.get_logger(__name__)current_user={'user':None,'login_time':None,'timeout':int(settings.LOGIN_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>>: ')db=common.conn_db()if db.get(name):if password == db.get(name).get('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()#===============>db.json
{"egon": {"password": "123", "money": 3000}, "alex": {"password": "alex3714", "money": 30000}, "wsb": {"password": "3714", "money": 20000}}#===============>common.py
from conf import settings
import logging
import logging.config
import jsondef get_logger(name):logging.config.dictConfig(settings.LOGGING_DIC)  # 導入上面定義的logging配置logger = logging.getLogger(name)  # 生成一個log實例return loggerdef conn_db():db_path=settings.DB_PATHdic=json.load(open(db_path,'r',encoding='utf-8'))return dic#===============>access.log
[2017-10-21 19:08:20,285][MainThread:10900][task_id:core.src][src.py:19][INFO][登錄成功]
[2017-10-21 19:08:32,206][MainThread:10900][task_id:core.src][src.py:19][INFO][登錄成功]
[2017-10-21 19:08:37,166][MainThread:10900][task_id:core.src][src.py:24][ERROR][用戶名不存在]
[2017-10-21 19:08:39,535][MainThread:10900][task_id:core.src][src.py:24][ERROR][用戶名不存在]
[2017-10-21 19:08:40,797][MainThread:10900][task_id:core.src][src.py:24][ERROR][用戶名不存在]
[2017-10-21 19:08:47,093][MainThread:10900][task_id:core.src][src.py:24][ERROR][用戶名不存在]
[2017-10-21 19:09:01,997][MainThread:10900][task_id:core.src][src.py:19][INFO][登錄成功]
[2017-10-21 19:09:05,781][MainThread:10900][task_id:core.src][src.py:24][ERROR][用戶名不存在]
[2017-10-21 19:09:29,878][MainThread:8812][task_id:core.src][src.py:19][INFO][登錄成功]
[2017-10-21 19:09:54,117][MainThread:9884][task_id:core.src][src.py:19][INFO][登錄成功]
View Code

?

  

轉載于:https://www.cnblogs.com/luckchao/p/8270483.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/453692.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/453692.shtml
英文地址,請注明出處:http://en.pswp.cn/news/453692.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux 狀態命令之 sar

簡介 sar&#xff08;System Activity Reporter 系統活動情況報告&#xff09;是目前 Linux 上最為全面的系統性能分析工具之一&#xff0c;可以從多方面對系統的活動進行報告&#xff0c;包括&#xff1a;文件的讀寫情況、系統調用的使用情況、磁盤 I/O、CPU 效率、內存使用狀…

解決eclipse + pydev 編譯過程中有中文的問題

最近在學習python編程&#xff0c;開發環境設置好了&#xff0c;是用eclipse pydev 來做開發的環境&#xff0c;配置好了之后&#xff0c;需要解決的一個關鍵問題就是老問題了&#xff1a;如何解決代碼中的中文問題。。。 其實但我們在配置編程環境的時候&#xff0c;就需要設…

程序員的思考--終于確定了自己的技術發展方向

經過了將近5年的工作沉淀以后&#xff0c;終于確定了自己的職業發展方向。從現在開始終于可以有的放矢了&#xff0c;不再迷茫了。回想以往&#xff0c;找到這個方向&#xff0c;確實不是一件容易的事情&#xff0c;一路也是迷茫的走過來&#xff0c;隨著知識和工作經驗的積累&…

mysql正在運行安全文件怎么辦_MySQL服務器運行的安全文件化選項,所以它不能執行該語句什么情? 愛問知識人...

MySQL的事務支持不是綁定在MySQL服務器本身&#xff0c;而是與存儲引擎相關1。MyISAM&#xff1a;不支持事務&#xff0c;用于只讀程序提高性能 2。InnoDB&#xff1a;支持ACID事務、行級鎖、并發 3。Berkeley DB&#xff1a;支持事務一個事務是一個連續的一組數據庫操作&#…

C++項目參考解答:累加求圓周率

【項目-累加求圓周率】 用例如以下公式求π的近似值&#xff08;計算直到最后一項的絕對值小于10?5&#xff09; π41?1315?17...【參考解答】 #include <iostream> using namespace std; int main( ) {int n,sign;double total,f;n1;total0;sign1;f1; //用f代表待累加…

[ASP.NET AJAX]類似.NET框架的JavaScript擴展

最近AJAX風靡全世界&#xff0c;在CommunityServer中他運用了自己定義的封裝了js&#xff0c;并且可以跨瀏覽器&#xff0c;在較小的應用程序中&#xff0c;他比較適合&#xff0c;而且使用也比較簡單。但是對微軟的Microsoft AJAX還是一點不了解的我&#xff0c;從今天開始也要…

mysql 連接 指定字符集_關于Mysql連接池配置指定字符集的問題

問題是這樣的&#xff0c;我在寫一個網站&#xff0c;打算使用連接池。我使用J2EE開發&#xff0c;開始使用的是直連的方式&#xff0c;附上代碼public class ConnDb {private String getDriver "com.mysql.jdbc.Driver";private String getUrl "jdbc:mysql:/…

【原】iOS:手把手教你發布代碼到CocoaPods(Trunk方式)

概述 關于CocoaPods的介紹不在本文的主題范圍內&#xff0c;如果你是iOS開發者卻不知道CocoaPods&#xff0c;那可能要面壁30秒了。直奔主題&#xff0c;這篇文章主要介紹如果把你的代碼發布到CocoaPods代碼庫中&#xff0c;讓別人可以使用“pod search yourOpenProject”命令查…

kafka tool 查看指定group下topic的堆積數量_ELK架構下利用Kafka Group實現Logstash的高可用...

系統運維的過程中&#xff0c;每一個細節都值得我們關注下圖為我們的基本日志處理架構所有日志由Rsyslog或者Filebeat收集&#xff0c;然后傳輸給Kafka&#xff0c;Logstash作為Consumer消費Kafka里邊的數據&#xff0c;分別寫入Elasticsearch和Hadoop&#xff0c;最后使用Kiba…

jquery flot pie畫餅圖

具體效果如下&#xff1a; 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv"Content-Type" content"text/html; charsetUTF-8"> 5 <title>Insert title here</title> 6 <script language"javas…

研發管理:產品研發團隊的早會

百度百科定義:研發管理就是在研發體系結構設計和各種管理理論基礎之上&#xff0c;借助信息平臺對研發過程中進行的團隊建設、流程設計、績效管理、風險管理、成本管理、項目管理和知識管理等的一系列協調活動。[詳細] 產品研發團隊在履行各種產品研發過程中&#xff0c;從大的…

mysql fetch rows_差異mysql_fetch_array()和mysql_fetch_rows()函數_mysql

區別mysql_fetch_array()和mysql_fetch_rows()函數form:http://www.uphtm.com/php/254.html如果我們不仔細看會發現象mysql_fetch_array()和mysql_fetch_rows()函數沒有什么區別&#xff0c;但是細細的看你會發現它們區別還是蠻大了&#xff0c;如果各位對于此函數的區別不了解…

Linux 狀態命令之網絡狀態 iftop - 查看實時帶寬流量

簡介 Linux 中查看網卡流量工具有 iptraf、iftop 以及 nethogs 等&#xff0c;iftop 可以用來監控網卡的實時流量(可以指定網段)、反向解析IP、顯示端口信息等。 安裝 CentOS yum 方式 # 安裝依賴 yum install flex byacc libpcap ncurses ncurses-devel libpcap-develyum …

Spring Boot 使用常見問題

Json格式化時間&#xff0c;時區設置 spring.jackson.time-zoneGMT8 spring.jackson.date-formatyyyy-MM-dd HH:mm:ss json數據無法序列化到RequestBody對象中 SpringMVC restful 注解之RequestBody進行json與object轉換 轉載于:https://www.cnblogs.com/tonyq/p/7890497.html

Angular15 利用ng2-file-upload實現文件上傳

待更新 轉載于:https://www.cnblogs.com/NeverCtrl-C/p/8279246.html

解讀設計模式----簡單工廠模式(SimpleFactory Pattern),你要什么我就給你什么

本文首發于博客園,地址:http://www.cnblogs.com/beniao/archive/2008/08/09/1263318.html 一、模式概述 從設計模式的類型上來說&#xff0c;簡單工廠模式是屬于創建型模式&#xff0c;又叫做靜態工廠方法&#xff08;Static Factory Method&#xff09;模式&#xff0c;但不屬…

Memcached常用操作

memcached是一個高性能的、分布式內存對象緩存系統&#xff0c;應用廣泛。 通過緩存數據庫查詢結果&#xff0c;減少數據庫訪問次數&#xff0c;以提高動態Web應用的速度、 提高可擴展性。 它可以應對任意多個連接&#xff0c;使用非阻塞的網絡IO。由于它的工作機制是在內存中開…

android自定義金額輸入鍵盤_Android 自定義控件 - 仿支付寶數字鍵盤

原標題&#xff1a;Android 自定義控件 - 仿支付寶數字鍵盤簡介在一些帶有支付功能的 App 中&#xff0c;輸入的密碼一般只能是純數字&#xff0c;雖然我們可以指定 EditText 輸入框只能輸入數字&#xff0c;但是為了提供用戶的使用體驗&#xff0c;我們往往更傾向于使用自定義…

博客目錄(python相關)

python 相關 文件格式相關系列 Python 第三方模塊之 beautifulsoup&#xff08;bs4&#xff09;- 解析 HTML Python 第三方模塊之 ElementTree&#xff08;ET&#xff09;- 解析XML文件 Python 第三方模塊之 lxml - 解析 HTML 和 XML 文件 python 第三方模塊 yaml - 處理 …

項目主體思索

1&#xff1a;分布式定義; 2&#xff1a;SSO集成方式 3&#xff1a;menu動態菜單的添加 4&#xff1a;tag頁面展示; 5&#xff1a;tiles的jsp復用&#xff1b; 暫時就想到這些了&#xff0c;以后繼續補充。轉載于:https://www.cnblogs.com/siyan/p/8286738.html