中文字幕理论片,69视频免费在线观看,亚洲成人app,国产1级毛片,刘涛最大尺度戏视频,欧美亚洲美女视频,2021韩国美女仙女屋vip视频

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
常用的模塊

1.模塊、包和相關(guān)語法

使用模塊有什么好處?

  1. 最大的好處是大大提高了代碼的可維護(hù)性。其次,編寫代碼不必從零開始。當(dāng)一個(gè)模塊編寫完畢,就可以被其他地方引用。我們在編寫程序的時(shí)候,也經(jīng)常引用其他模塊,包括Python內(nèi)置的模塊和來自第三方的模塊。
  2. 使用模塊還可以避免函數(shù)名和變量名沖突。每個(gè)模塊有獨(dú)立的命名空間,因此相同名字的函數(shù)和變量完全可以分別存在不同的模塊中,所以,我們自己在編寫模塊時(shí),不必考慮名字會(huì)與其他模塊沖突

模塊分類

模塊分為三種:

  • 內(nèi)置標(biāo)準(zhǔn)模塊(又稱標(biāo)準(zhǔn)庫)執(zhí)行help('modules')查看所有python自帶模塊列表
  • 第三方開源模塊,可通過pip install 模塊名 聯(lián)網(wǎng)安裝
  • 自定義模塊

模塊調(diào)用

import modulefrom module import xxfrom module.xx.xx import xx as rename  from module.xx.xx import *
View Code
模塊一旦被調(diào)用,即相當(dāng)于執(zhí)行了另外一個(gè)py文件里的代碼

自定義模塊

這個(gè)最簡單, 創(chuàng)建一個(gè).py文件,就可以稱之為模塊,就可以在另外一個(gè)程序里導(dǎo)入

模塊查找路徑

import sysprint(sys.path)['', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages']
View Code

python解釋器會(huì)按照列表順序去依次到每個(gè)目錄下去匹配你要導(dǎo)入的模塊名,只要在一個(gè)目錄下匹配到了該模塊名,就立刻導(dǎo)入,不再繼續(xù)往后找。

注意列表第一個(gè)元素為空,即代表當(dāng)前目錄,所以你自己定義的模塊在當(dāng)前目錄會(huì)被優(yōu)先導(dǎo)入。

開源模塊安裝、使用

https://pypi.python.org/pypi?是python的開源模塊庫

1.直接在上面這個(gè)頁面上點(diǎn)download,下載后,解壓并進(jìn)入目錄,執(zhí)行以下命令完成安裝

編譯源碼    python setup.py build安裝源碼    python setup.py install
View Code

2.直接通過pip安裝

pip3 install paramiko #paramiko 是模塊名
View Code

pip命令會(huì)自動(dòng)下載模塊包并完成安裝。

軟件一般會(huì)被自動(dòng)安裝你python安裝目錄的這個(gè)子目錄里

/your_python_install_path/3.6/lib/python3.6/site-packages

pip命令默認(rèn)會(huì)連接在國外的python官方服務(wù)器下載,速度比較慢,你還可以使用國內(nèi)的豆瓣源,數(shù)據(jù)會(huì)定期同步國外官網(wǎng),速度快好多

sudo pip install -i http://pypi.douban.com/simple/ alex_sayhi --trusted-host pypi.douban.com   #alex_sayhi是模塊名

使用

下載后,直接導(dǎo)入使用就可以,跟自帶的模塊調(diào)用方法無差,演示一個(gè)連接linux執(zhí)行命令的模塊

#coding:utf-8import paramikossh = paramiko.SSHClient()ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())ssh.connect('192.168.1.108', 22, 'alex', '123')stdin, stdout, stderr = ssh.exec_command('df')print(stdout.read())ssh.close();執(zhí)行命令 - 通過用戶名和密碼連接服務(wù)器
View Code

包(Package)

當(dāng)你的模塊文件越來越多,就需要對模塊文件進(jìn)行劃分,比如把負(fù)責(zé)跟數(shù)據(jù)庫交互的都放一個(gè)文件夾,把與頁面交互相關(guān)的放一個(gè)文件夾

.└── my_proj    ├── crm #代碼目錄    │   ├── admin.py    │   ├── apps.py    │   ├── models.py    │   ├── tests.py    │   └── views.py    ├── manage.py    └── my_proj #配置文件目錄        ├── settings.py        ├── urls.py        └── wsgi.py

像上面這樣,一個(gè)文件夾管理多個(gè)模塊文件,這個(gè)文件夾就被稱為包,包就是文件夾,但該文件夾下必須存在 __init__.py 文件, 該文件的內(nèi)容可以為空。__int__.py用于標(biāo)識(shí)當(dāng)前文件夾是一個(gè)包。

那不同包之間的模塊互相導(dǎo)入呢?

crm/views.py內(nèi)容

def sayhi():    print('hello world!')
View Code

通過manage.py調(diào)用

from crm import viewsviews.sayhi()
View Code

跨模塊導(dǎo)入

import syssys.path.append("C:\\Users\Administrator\PycharmProjects\myFirstpro\chapter4模塊的學(xué)習(xí)\my_proj")#這個(gè)是靜態(tài)路徑,右鍵path它的路徑。注意是找my_proj這個(gè)路徑這樣才能from..                                                                                   ##如果加了proj這個(gè)路徑,它就會(huì)自動(dòng)往里邊去找,直接import settings就可以了#sys.path.append(r"C:\Users\Administrator\PycharmProjects\myFirstpro\chapter4模塊的學(xué)習(xí)\my_proj") ##加rprint(sys.path)from proj import settingsdef sayhi():    print('Hello World!')
View Code
import sys,osprint(dir())print(‘file’,_file_)BASE_DIR = os.path.dirname(os.path.dirname(_file_))print(BASE_DIR)sys.path.append(BASE_DIR)  #這個(gè)是動(dòng)態(tài)路徑 from proj import settingsdef sayhi():    print('Hello world!')打?。篬'__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'os', 'sys']C:/Users/Administrator/PycharmProjects/myFirstpro/chapter4模塊的學(xué)習(xí)/my_proj/crm/views.pyC:/Users/Administrator/PycharmProjects/myFirstpro/chapter4模塊的學(xué)習(xí)/my_projin proj/settings.py
View Code
import sys,osprint(dir())print(‘file’,_file_)BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(_file_))) #這是絕對路徑,這樣在哪里執(zhí)行都沒有問題了print(BASE_DIR)sys.path.append(BASE_DIR)from proj import settingsdef sayhi():    print('Hello world!')
View Code

絕對導(dǎo)入&相對導(dǎo)入

在linux里可以通過cd ..回到上一層目錄 ,cd ../.. 往上回2層,這個(gè)..就是指相對路徑,在python里,導(dǎo)入也可以通過..

├── __init__.py├── crm│   ├── __init__.py│   ├── admin.py│   ├── apps.py│   ├── models.py│   ├── tests.py│   ├── views.py  ├── manage.py   └── proj    ├── __init__.py    ├── settings.py    ├── urls.py    └── wsgi.py#from crm import modelsfrom . import models  #from crm import models 這兩個(gè)是一樣的 #. 就叫相對導(dǎo)入,因?yàn)樗鼈z在同一級目錄def sayhi():    print('Hello world!')#執(zhí)行manage
View Code

?

time & datetime 模塊

在python里通常有下面幾種表示時(shí)間的方式:

  1. 時(shí)間戳:時(shí)間戳表示的是從1970年1月1日00:00:00開始按秒計(jì)算的偏移量。我們運(yùn)行“type(time.time())”,返回的是float類型。
  2. 格式化的時(shí)間字符串
  3. 元組(struct_time)共九個(gè)元素。返回struct_time的函數(shù)主要有g(shù)mtime(),localtime(),strptime()。由于Python的time模塊實(shí)現(xiàn)主要調(diào)用C庫,所以各個(gè)平臺(tái)可能有所不同。這種方式元組中的幾種元素:
索引(Index)    屬性(Attribute)          值(Values)0           tm_year(年)                   比如2011 1           tm_mon(月)                 1 - 122           tm_mday(日)                  1 - 313           tm_hour(時(shí))                  0 - 234           tm_min(分)                 0 - 595           tm_sec(秒)                 0 - 616           tm_wday(weekday)             0 - 6(0表示周日)7           tm_yday(一年中的第幾天)      1 - 3668           tm_isdst(是否是夏令時(shí))         默認(rèn)為-1

time.localtime()將當(dāng)前時(shí)間轉(zhuǎn)為當(dāng)前時(shí)區(qū)的struct_time;wday 0-6表示周日到周六;ydat 1-366 一年中的第幾天;?isdst 是否為夏令時(shí),默認(rèn)為-1;

time.gmtime()

>>>import time>>>time.time() #返回當(dāng)前的時(shí)間戳1507808689.675603>>>time.localtime() #將一個(gè)時(shí)間戳轉(zhuǎn)換為當(dāng)前時(shí)區(qū)的struct_timetime.struct_time( tm_year=2017, tm_mon=10, tm_mday=12, tm_hour=19, tm_min=45, tm_sec=61, tm_wday=3, tm_yday=285, tm_isdst=0) #打印本地時(shí)間>>>time.gmtime() #將一個(gè)時(shí)間戳轉(zhuǎn)換為UTC標(biāo)準(zhǔn)時(shí)間,比我們晚8個(gè)小時(shí)time.struct_time( tm_year=2017, tm_mon=10, tm_mday=12, tm_hour=11, tm_min=47, tm_sec=51, tm_wday=3, tm_yday=285, tm_isdst=0)
View Code
>>>a = time.localtime(1403232424) >>>atime.struct_time( tm_year=2014, tm_mon=6, tm_mday=20, tm_hour=10, tm_min=47, tm_sec=4, tm_wday=4, tm_yday=171, tm_isdst=0) 
View Code

字符串的拼接 、 time.mktime()

>>>'%s-%s-%s'%(a.tm_year, a.tm_mon, a.tm_mday) #可以進(jìn)行拼接‘2017-10-12’>>>time.mktime(a)  #將一個(gè)struct_time轉(zhuǎn)化為時(shí)間戳。140323242.0
View Code

time.asctime() ?(外國人常使用的時(shí)間形式) ?、time.ctime()將當(dāng)前時(shí)間轉(zhuǎn)換為一個(gè)字符串str

>>>time.asctime()  #把一個(gè)表示時(shí)間的元組或者struct_time表示為這種形式:'Sun Oct 1 12:04:38 2017'。'Thu Oct 12 19:52:10 2017'>>>time.ctime()  #把一個(gè)時(shí)間戳(按秒計(jì)算的浮點(diǎn)數(shù))轉(zhuǎn)化為time.asctime()的形式。相當(dāng)于time.asctime(time.localtime(secs))'Thu Oct 12 19:52:36 2017'>>>time.ctime(123232)'Fri Jan  2 18:13:52 1970'>>>time.ctime(0)'Thu Jan  1 08:00:00 1970'
View Code

time.sleep(secs):線程推遲指定的時(shí)間運(yùn)行。單位為秒。

time.strftime( ‘%Y-%m-%d ?%H:%M:%S ?%A %P %U’ )?轉(zhuǎn)化為格式化的字符串 ? ? ? ? time.strptime(s, ?‘%Y-%m-%d ?%H:%M:%S ’ ) ?把格式化字符串進(jìn)行反轉(zhuǎn)為struct_time

time.strftime(a,b)??,?a為格式化字符串格式 ?,?b為時(shí)間戳,一般用localtime()

>>>atime.struct_time(tm_year=1974, tm_mon=6, tm_day=13, tm_hour=10, tm_min=40, tm_sec=42, tm_wday=3, tm_yday=164, tm_isdst=0)>>>time.strftime('%Y-%m-%d %H:%M:%S',a)   #把一個(gè)代表時(shí)間的元組或者struct_time(如由time.localtime()和time.gmtime()返回)轉(zhuǎn)化為格式化的時(shí)間字符串'1974-06-13 10:40:42'>>>time.strftime('%Y-%m-%d %H:%M:%S',) #不加就默認(rèn)當(dāng)前時(shí)間'2017-10-12 19:56:31'>>>time.strftime('%Y-%m-%d %H:%M:%S %A',a) # %A 星期幾'1974-06-13 10:40:42 Thursday'>>>time.strftime('%Y-%m-%d %H:%M:%S %p',a) #%p  AM or PM'1974-06-13 10:40:42 AM'>>>time.strftime('%Y-%m-%d %H:%M:%S %U',a) #%U一年的第幾周'1974-06-13 10:40:42 23'>>> import time>>> print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()))2018-07-28 14:12:17
View Code
>>>s=time.strftime('%Y-%m-%d %H:%M:%S')>>>s'2017 10-12 20:00:56'time.strptime(s, '%Y %m-%d %H:%M:%S')  #反轉(zhuǎn)   #把一個(gè)格式化時(shí)間字符串轉(zhuǎn)化為struct_timetime.struct_time(tm_year=2017, tm_mon=,10, tm_day=12, tm_hour=20, tm_min=1, tm_sec=26, tm_wday=3, tm_yday=285, tm_isdst=-1)>>>time.mktime(s) #把時(shí)間對象又變成時(shí)間戳1507809686.0
View Code

datatime模塊

datetime.datetime.now()?返回當(dāng)前的datetime日期類型,d.timestamp(),d.today(), d.year,d.timetuple()等方法可以調(diào)用

>>>import datetime>>>datetime.datetime.now()  #a.timestamp(),a.today(), a.year,a.timetuple()等方法可以調(diào)用;打印出下面的時(shí)間datetime.datetime(2017, 10, 12, 20, 8, 19, 393189)
View Code

datetime.date.fromtimestamp() ?#把時(shí)間戳轉(zhuǎn)化為datetime類型

>>>d2= datetime.date.fromtimestamp(time.time()) #快速的把時(shí)間戳拿到它的年月日>>>d2datetime.date(2017, 10, 12)>>>d2.timetuple()time.struct_time(tm_year=2017, tm_mon=10, tm_mday=12, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=285, tm_isdst=-1)  #其中三個(gè)為0,顯示不了
View Code

重點(diǎn)是進(jìn)行時(shí)間的運(yùn)算 ?

datetime.datetime.now() (-) datetime.timedelta()

>>>t = datetime.timedelta(1)>>>datetime.datetime.now() - tdatetime.datetime(2017, 10, 11, 20, 12, 37, 106915)>>>datetime.datetime.now() - datetime.timedelta(days=1)datetime.datetime(2017, 10, 11, 20, 12, 37, 106915)>>>datetime.datetime.now() - datetime.timedelta(hours=3)datetime.datetime(2017, 10, 12, 17, 13, 14, 617201)>>>datetime.datetime.now()   datetime.timedelta(minutes=10)datetime.datetime(2017, 10, 12, 20, 24, 2, 178282)>>>datetime.datetime.now()   datetime.timedelta(seconds=10)datetime.datetime(2017, 10, 12, 20, 14, 23, 858086)
View Code

時(shí)間的替換

>>>d.replace()datetime.datetime(2017, 10, 12, 20, 15, 17,457249)>>>d.replace(year=2016)datetime.datetime(2016, 10, 12, 20, 15, 17,457249)>>>d.replace(year=2016,month=8)datetime.datetime(2016, 8, 12, 20, 15, 17,457249)
View Code

random模塊

>>> random.randrange(1,10) #返回1-10之間的一個(gè)隨機(jī)數(shù),不包括10>>> random.randint(1,10) #返回1-10之間的一個(gè)隨機(jī)數(shù),包括10>>> random.randrange(0, 100, 2) #隨機(jī)選取0到100間的偶數(shù)>>> random.random()  #返回一個(gè)隨機(jī)浮點(diǎn)數(shù)>>> random.choice('abce3#$@1') #返回一個(gè)給定數(shù)據(jù)集合中的隨機(jī)字符'#'>>> random.sample('abcdefghij',3)  #從多個(gè)字符中選取特定數(shù)量的字符['a', 'd', 'b']#生成隨機(jī)字符串>>> import string >>> ''.join(random.sample(string.ascii_lowercase   string.digits, 6)) '4fvda1'#洗牌>>> a[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> random.shuffle(a)>>> a[3, 0, 7, 2, 1, 6, 5, 8, 9, 4]
View Code

os模塊

os 模塊提供了很多允許你的程序與操作系統(tǒng)直接交互的功能

得到當(dāng)前工作目錄,即當(dāng)前Python腳本工作的目錄路徑: os.getcwd()返回指定目錄下的所有文件和目錄名:os.listdir()函數(shù)用來刪除一個(gè)文件:os.remove()刪除多個(gè)目錄:os.removedirs(r“c:\python”)檢驗(yàn)給出的路徑是否是一個(gè)文件:os.path.isfile()檢驗(yàn)給出的路徑是否是一個(gè)目錄:os.path.isdir()判斷是否是絕對路徑:os.path.isabs()檢驗(yàn)給出的路徑是否真地存:os.path.exists()返回一個(gè)路徑的目錄名和文件名:os.path.split()     e.g os.path.split('/home/swaroop/byte/code/poem.txt') 結(jié)果:('/home/swaroop/byte/code', 'poem.txt') 分離擴(kuò)展名:os.path.splitext()       e.g  os.path.splitext('/usr/local/test.py')    結(jié)果:('/usr/local/test', '.py')獲取路徑名:os.path.dirname()獲得絕對路徑: os.path.abspath()  獲取文件名:os.path.basename()運(yùn)行shell命令: os.system()讀取操作系統(tǒng)環(huán)境變量HOME的值:os.getenv("HOME") 返回操作系統(tǒng)所有的環(huán)境變量: os.environ 設(shè)置系統(tǒng)環(huán)境變量,僅程序運(yùn)行時(shí)有效:os.environ.setdefault('HOME','/home/alex')給出當(dāng)前平臺(tái)使用的行終止符:os.linesep    Windows使用'\r\n',Linux and MAC使用'\n'指示你正在使用的平臺(tái):os.name       對于Windows,它是'nt',而對于Linux/Unix用戶,它是'posix'重命名:os.rename(old, new)創(chuàng)建多級目錄:os.makedirs(r“c:\python\test”)創(chuàng)建單個(gè)目錄:os.mkdir(“test”)獲取文件屬性:os.stat(file)修改文件權(quán)限與時(shí)間戳:os.chmod(file)獲取文件大?。簅s.path.getsize(filename)結(jié)合目錄名與文件名:os.path.join(dir,filename)改變工作目錄到dirname: os.chdir(dirname)獲取當(dāng)前終端的大小: os.get_terminal_size()殺死進(jìn)程: os.kill(10884,signal.SIGKILL)
View Code

sys模塊

sys.argv           命令行參數(shù)List,第一個(gè)元素是程序本身路徑sys.exit(n)        退出程序,正常退出時(shí)exit(0)sys.version        獲取Python解釋程序的版本信息sys.maxint         最大的Int值sys.path           返回模塊的搜索路徑,初始化時(shí)使用PYTHONPATH環(huán)境變量的值sys.platform       返回操作系統(tǒng)平臺(tái)名稱sys.stdout.write('please:')  #標(biāo)準(zhǔn)輸出 , 引出進(jìn)度條的例子, 注,在py3上不行,可以用print代替val = sys.stdin.readline()[:-1] #標(biāo)準(zhǔn)輸入sys.getrecursionlimit() #獲取最大遞歸層數(shù)sys.setrecursionlimit(1200) #設(shè)置最大遞歸層數(shù)sys.getdefaultencoding()  #獲取解釋器默認(rèn)編碼sys.getfilesystemencoding  #獲取內(nèi)存數(shù)據(jù)存到文件里的默認(rèn)編碼
View Code

shutil模塊

高級的 文件、文件夾、壓縮包 處理模塊

shutil.copyfileobj(fsrc, fdst[, length])
將文件內(nèi)容拷貝到另一個(gè)文件中

import shutilshutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))
View Code

shutil.copyfile(src, dst)
拷貝文件

shutil.copyfile('f1.log', 'f2.log') #目標(biāo)文件無需存在
View Code

shutil.copymode(src, dst)
僅拷貝權(quán)限。內(nèi)容、組、用戶均不變

shutil.copymode('f1.log', 'f2.log') #目標(biāo)文件必須存在
View Code

shutil.copystat(src, dst)
僅拷貝狀態(tài)的信息,包括:mode bits, atime, mtime, flags

shutil.copystat('f1.log', 'f2.log') #目標(biāo)文件必須存在
View Code

shutil.copy(src, dst)
拷貝文件和權(quán)限

import shutilshutil.copy('f1.log', 'f2.log')
View Code

shutil.copy2(src, dst)
拷貝文件和狀態(tài)信息

import shutilshutil.copy2('f1.log', 'f2.log')
View Code

shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
遞歸的去拷貝文件夾

import shutilshutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目標(biāo)目錄不能存在,注意對folder2目錄父級目錄要有可寫權(quán)限,ignore的意思是排除
View Code

shutil.rmtree(path[, ignore_errors[, onerror]])
遞歸的去刪除文件

import shutilshutil.rmtree('folder1')
View Code

shutil.move(src, dst)
遞歸的去移動(dòng)文件,它類似mv命令,其實(shí)就是重命名。

import shutilshutil.move('folder1', 'folder3')
View Code

shutil.make_archive(base_name, format,...)
創(chuàng)建壓縮包并返回文件路徑,例如:zip、tar
創(chuàng)建壓縮包并返回文件路徑,例如:zip、tar

  • base_name: 壓縮包的文件名,也可以是壓縮包的路徑。只是文件名時(shí),則保存至當(dāng)前目錄,否則保存至指定路徑,

如 data_bak =>保存至當(dāng)前路徑
如:/tmp/data_bak =>保存至/tmp/

    • format: 壓縮包種類,“zip”, “tar”, “bztar”,“gztar”
    • root_dir: 要壓縮的文件夾路徑(默認(rèn)當(dāng)前目錄)
    • owner: 用戶,默認(rèn)當(dāng)前用戶
    • group: 組,默認(rèn)當(dāng)前組
    • logger: 用于記錄日志,通常是logging.Logger對象
#將 /data 下的文件打包放置當(dāng)前程序目錄import shutilret = shutil.make_archive("data_bak", 'gztar', root_dir='/data')#將 /data下的文件打包放置 /tmp/目錄import shutilret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data')
View Code

shutil 對壓縮包的處理是調(diào)用 ZipFile 和 TarFile 兩個(gè)模塊來進(jìn)行的,詳細(xì):
zipfile壓縮&解壓縮

import zipfile# 壓縮z = zipfile.ZipFile('laxi.zip', 'w')z.write('a.log')z.write('data.data')z.close()# 解壓z = zipfile.ZipFile('laxi.zip', 'r')z.extractall(path='.')z.close()
View Code

tarfile壓縮&解壓縮

import tarfile# 壓縮>>> t=tarfile.open('/tmp/egon.tar','w')>>> t.add('/test1/a.py',arcname='a.bak')>>> t.add('/test1/b.py',arcname='b.bak')>>> t.close()# 解壓>>> t=tarfile.open('/tmp/egon.tar','r')>>> t.extractall('/egon')>>> t.close()
View Code

序列化模塊

序列化是指把內(nèi)存里的數(shù)據(jù)類型轉(zhuǎn)變成字符串,以使其能存儲(chǔ)到硬盤或通過網(wǎng)絡(luò)傳輸?shù)竭h(yuǎn)程,因?yàn)橛脖P或網(wǎng)絡(luò)傳輸時(shí)只能接受bytes

用于序列化的兩個(gè)模塊

  • json,用于字符串 和 python數(shù)據(jù)類型間進(jìn)行轉(zhuǎn)換
  • pickle,用于python特有的類型 和 python的數(shù)據(jù)類型間進(jìn)行轉(zhuǎn)換

?

  JSON:

  優(yōu)點(diǎn):跨語言、體積小

  缺點(diǎn):只能支持int\str\list\tuple\dict

  Pickle:

  優(yōu)點(diǎn):專為python設(shè)計(jì),支持python所有的數(shù)據(jù)類型

  缺點(diǎn):只能在python中使用,存儲(chǔ)數(shù)據(jù)占空間大

?

Json模塊提供了四個(gè)功能:dumps、dump、loads、load

pickle模塊提供了四個(gè)功能:dumps、dump、loads、load

import pickledata = {'k1':123,'k2':'Hello'}# pickle.dumps 將數(shù)據(jù)通過特殊的形式轉(zhuǎn)換位只有python語言認(rèn)識(shí)的字符串p_str = pickle.dumps(data)print(p_str)#pickle.dump 將數(shù)據(jù)通過特殊的形式轉(zhuǎn)換位只有python語言認(rèn)識(shí)的字符串,并寫入文件with open('D:/result.pk','wb',encoding='utf8') as fp:    pickle.dump(data,fp)import json# json.dumps 將數(shù)據(jù)通過特殊的形式轉(zhuǎn)換位所有程序語言都認(rèn)識(shí)的字符串j_str = json.dumps(data)print(j_str)#pickle.dump 將數(shù)據(jù)通過特殊的形式轉(zhuǎn)換位只有python語言認(rèn)識(shí)的字符串,并寫入文件with open('D:/result.json','wb',encoding='utf8') as fp:    json.dump(data,fp)
View Code
#序列化data = {    'roles' : [        {'role':'monster','type':'pig','life':50},        {'role':'hero','type':'關(guān)羽','life':80},    ]}f = open('game_status','w')f.write(str(data))  #str把字典轉(zhuǎn)換成字符串
View Code
#反序列 把字符轉(zhuǎn)成內(nèi)存數(shù)據(jù)類型data = {    'roles' : [        {'role':'monster','type':'pig','life':50},        {'role':'hero','type':'關(guān)羽','life':80},    ]}# f = open('game_status','w')# f.write(str(data))f = open('game_status','r')d = f.read()d = eval(d) #字符串轉(zhuǎn)成字典print(d['roles'])
View Code

序列化json模塊

import jsondata = {    'roles' : [        {'role':'monster','type':'pig','life':50},        {'role':'hero','type':'關(guān)羽','life':80},    ]}d = json.dumps(data) #僅換成字符串print(d,type(d)) #strd2 = json.loads(d) #把字符串轉(zhuǎn)成相應(yīng)的數(shù)據(jù)類型print(d2,type(d2)) #dictprint(d2['roles'])
View Code
打?。簕"roles": [{"role": "monster", "type": "pig", "life": 50}, {"role": "hero", "type": "\u5173\u7fbd", "life": 80}]} <class 'str'>{'roles': [{'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '關(guān)羽', 'life': 80}]} <class 'dict'>[{'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '關(guān)羽', 'life': 80}]
View Code

注意loads和load、 dumps和dump的用法和區(qū)別:

dumps是將dict轉(zhuǎn)化成str格式,loads是將str轉(zhuǎn)化成dict格式。dump和load也是類似的功能,只是與文件操作結(jié)合起來了。

import jsondata = {    'roles' : [        {'role':'monster','type':'pig','life':50},        {'role':'hero','type':'關(guān)羽','life':80},    ]}f = open("test.json", "w")json.dump(data, f)  #轉(zhuǎn)成字符串并寫入文件f = open("test.json","r")data = json.load(f) #print(data['roles'])
View Code
自動(dòng)生成一個(gè)test.json文件夾{"roles": [{"role": "monster", "type": "pig", "life": 50}, {"role": "hero", "type": "\u5173\u7fbd", "life": 80}]}打印出:[{'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '關(guān)羽', 'life': 80}]
View Code

只把數(shù)據(jù)類型轉(zhuǎn)換成字符串存到內(nèi)存里的意義? ?json.dumps ?  json.loads

  1.把你的內(nèi)存數(shù)據(jù),通過網(wǎng)絡(luò),共享給遠(yuǎn)程其他人;

  2.定義了不同語言的之前的交互規(guī)則。

    1.純文本, 壞處, 不能共享復(fù)雜的數(shù)據(jù)類型;

    2.xml, 壞處 , 占空間大;3.json, 簡單, 可讀性好。

import jsonf = open('json_file', 'w', encoding='utf-8')d = {'name':'alex', 'age':'23'} #字典l = [1,2,3,5,9,'rain']  #列表json.dump(d,f) #可以dump多次json.dump(l,f)自動(dòng)創(chuàng)建json_file的文件:{"name": "alex", "age": "23"}[1, 2, 3, 5, 9, "rain"]
View Code
import jsonf = open("json_file", 'r', encoding"utf-8")print(json.load(f))   #反序列化不能load多次,不要dump多次,load多次。只一次,為了避免問題。 json_load文件里邊字典和列表都在里邊不能load,會(huì)報(bào)錯(cuò)。
View Code

pickle(用法完全一樣)

import pickled = {'name' : 'alex' , 'age' : 22 }l = [1,2,3,4,'rain' ]pk = open("data.pkl", "w")print(pickle.dumps(d))   ##打印bytes類型 b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x04\x00\x00\x00alexq\x02X\x03\x00\x00\x00ageq\x03K\x16u.'
View Code
import pickled = {'name' : 'alex' , 'age' : 22 }l = [1,2,3,4,'rain' ]pk = open("data.pkl", "wb")print(pickle.dump(d,pk))  #二進(jìn)制的bytes類型的文本格式,存到了硬盤上。print(pickle.dump(l,pk) 自動(dòng)創(chuàng)建data.pkl文件夾:?}q (X   nameq X   alexq X   ageq K u. ?]q (K K K K X   rainq e.
View Code

從硬盤上讀取數(shù)據(jù)

import picklef = open("data.pkl", "rb")d = pickle.load(f)print(d)  #{'name': 'alex', 'age': 22}l = pickle.load(f)print(l) #[1, 2, 3, 4, 'rain']
View Code

序列化shelve模塊

shelve模塊是一個(gè)簡單的k,v將內(nèi)存數(shù)據(jù)通過文件持久化的模塊,可以持久化任何pickle可支持的python數(shù)據(jù)格式

#序列化import shelvef = shelve.open('shelve_test')  # 打開一個(gè)文件names = ["alex", "rain", "test"]info = {'name':'alex','age':22}f["names"] = names  # 持久化列表f['info_dic'] = info #持久化dictf.close()#反序列化import shelved = shelve.open('shelve_test')  # 打開一個(gè)文件print(d['names'])     #['alex', 'rain', 'test']print(d['info_dic'])  #{'name': 'alex', 'age': 22}#del d['test'] #還可以刪除
View Code
>>>f = shelve.open("shelve_test")>>>f<shelve.DbfilenameShelf object at 0x101dce9e8>>>>list(f.keys())['name', 'info_dic']>>>list(f.items())[('name', ['alex', 'rain', 'test']), ('info_dic', {'name': 'alex', 'age':22})]>>>f.get('names')['alex', 'rain', 'text']>>>f.get('info_dic'){'name': 'alex', 'age':22}>>>f['names'][1]'rain'>>>f['names'][1] = "Rain wang"  #不能這樣修改,修改不了,要直接賦值。>>>f['names'][1]None>>>f.close()>>>f = shelve.open("shelve_test")
View Code

import shelvef = shelve.open("shelve_test")f['scores'] = [1,2,3,4,5,6]print(f.get('scores'))f['scores'] = [1,2,3,'A',4,'B']print(f.get('scores'))
View Code

XML模塊

xml是實(shí)現(xiàn)不同語言或程序之間進(jìn)行數(shù)據(jù)交換的協(xié)議,跟json差不多,但json使用起來更簡單,不過,古時(shí)候,在json還沒誕生的黑暗年代,大家只能選擇用xml呀,至今很多傳統(tǒng)公司如金融行業(yè)的很多系統(tǒng)的接口還主要是xml。

xml的格式如下,就是通過<>節(jié)點(diǎn)來區(qū)別數(shù)據(jù)結(jié)構(gòu)的:

<?xml version="1.0"?><data>    <country name="Liechtenstein">        <rank updated="yes">2</rank>        <year>2008</year>        <gdppc>141100</gdppc>        <neighbor name="Austria" direction="E"/>        <neighbor name="Switzerland" direction="W"/>    </country>    <country name="Singapore">        <rank updated="yes">5</rank>        <year>2011</year>        <gdppc>59900</gdppc>        <neighbor name="Malaysia" direction="N"/>    </country>    <country name="Panama">        <rank updated="yes">69</rank>        <year>2011</year>        <gdppc>13600</gdppc>        <neighbor name="Costa Rica" direction="W"/>        <neighbor name="Colombia" direction="E"/>    </country></data>
View Code
import xml.etree.ElementTree as ETtree = ET.parse("xmltest.xml")  #openroot = tree.getroot() #f.seek(0)print(root.tag)#遍歷xml文檔for child in root:    print('-------------',child.tag,child.attrib)    #print(child.tag, child.attrib)    for i in child:        print(i.tag,i.text)打印:data------------- country {'name': 'Liechtenstein'}rank 2year 2008gdppc 141100neighbor Noneneighbor None------------- country {'name': 'Singapore'}rank 5year 2011gdppc 59900neighbor None------------- country {'name': 'Panama'}rank 69year 2011gdppc 13600neighbor Noneneighbor None
View Code
import xml.etree.ElementTree as ETtree = ET.parse("xmltest.xml")  #openroot = tree.getroot() #f.seek(0)print(root.tag)#只遍歷year 節(jié)點(diǎn)for node in root.iter('year'):    print(node.tag,node.text)打?。篸atayear 2008year 2011year 2011
View Code
###################自己創(chuàng)建xml文檔#############################import xml.etree.ElementTree as ETnew_xml = ET.Element("namelist")     #rootname = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})age = ET.SubElement(name,"age",attrib={"checked":"no"})sex = ET.SubElement(name,"sex")n = ET.SubElement(name,"name")n = "alex"sex.text = 'man'name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})age = ET.SubElement(name2,"age")age.text = '19'et = ET.ElementTree(new_xml) #生成文檔對象et.write("test.xml", encoding="utf-8",xml_declaration=True)ET.dump(new_xml) #打印生成的格式打?。?lt;?xml version='1.0' encoding='utf-8'?><namelist>    <name enrolled="yes">    <age checked="no" />    <sex>man</sex></name>    <name enrolled="no">        <age>19</age>    </name></namelist>
View Code

configparser模塊(解析、配置文件)

此模塊用于生成和修改常見配置文檔,當(dāng)前模塊的名稱在 python 3.x 版本中變更為 configparser。

?好多軟件的常見配置文件格式如下:

##conf.ini文件[DEFAULT]ServerAliveInterval = 45Compression = yesCompressionLevel = 9ForwardX11 = yes[bitbucket.org]User = hg[topsecret.server.com]Port = 50022ForwardX11 = no
View Code
>>> import configparser>>> config = configparser.ConfigParser() #實(shí)例化生成一個(gè)對象>>> config.sections() #調(diào)用sections方法;在cmd里邊演示[]>>> config.read('example.ini')['example.ini']>>> config.sections() #調(diào)用sections方法(默認(rèn)不會(huì)讀取default方法)['bitbucket.org', 'topsecret.server.com']>>> 'bitbucket.org' in config #判斷元素是否在sections列表內(nèi)True>>> 'bytebong.com' in configFalse>>> config['bitbucket.org']['User'] #通過字典的形式取值'hg'>>> config['DEFAULT']['Compression']'yes'>>> topsecret = config['topsecret.server.com']>>> topsecret['ForwardX11']'no'>>> topsecret['Port']'50022'>>> for key in config['bitbucket.org']: print(key) #for循環(huán)bitbucket.org 字典的key...usercompressionlevelserveraliveintervalcompressionforwardx11>>> config['bitbucket.org']['ForwardX11']'yes'
View Code
import configparserconf = configparser.ConfigParser()  #先生成一個(gè)對象#print(conf.sections())  #[]conf.read('conf.ini')print(conf.sections())#['bitbucket.org', 'topsecret.server.com']print(conf.default_section) #DEFAULT# print(list(conf["bitbucket.org"].keys()))print(conf["bitbucket.org"]['User']) #hg
View Code
#循環(huán)import configparserconf = configparser.ConfigParser()  #先生成一個(gè)對象conf.read('conf.ini')for k,v in conf["bitbucket.org"].items():    print(k,v)#打?。簎ser hgserveraliveinterval 45compression yescompressionlevel 9forwardx11 yes
View Code
import configparserconf = configparser.ConfigParser()  conf.read('conf.ini')if 'user' in conf["bitbucket.org"]: #判斷是否在    print('in')
View Code
import configparserconf = configparser.ConfigParser()  #先生成一個(gè)對象conf.read("conf_text.ini")conf.add_section("group3")conf["group3"]['name'] = "alex"conf["group3"]['age'] = '22'conf.write(open('conf_test_mew.ini','w'))  ###改寫
View Code
import configparserconf = configparser.ConfigParser()  #先生成一個(gè)對象conf.read("conf_text.ini")#conf.remove_option("group1",'k2')conf.remove_section("group1")conf.write(open('conf_test2_mew.ini','w'))#刪完之后要保存
View Code

hashlib模塊

加密算法介紹

HASH

Hash,一般翻譯做“散列”,也有直接音譯為”哈希”的,就是把任意長度的輸入(又叫做預(yù)映射,pre-image),通過散列算法,變換成固定長度的輸出,該輸出就是散列值。這種轉(zhuǎn)換是一種壓縮映射,也就是,散列值的空間通常遠(yuǎn)小于輸入的空間,不同的輸入可能會(huì)散列成相同的輸出,而不可能從散列值來唯一的確定輸入值。

簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數(shù)。

HASH主要用于信息安全領(lǐng)域中加密算法,他把一些不同長度的信息轉(zhuǎn)化成雜亂的128位的編碼里,叫做HASH值.也可以說,hash就是找到一種數(shù)據(jù)內(nèi)容和數(shù)據(jù)存放地址之間的映射關(guān)系

MD5

什么是MD5算法

MD5訊息摘要演算法(英語:MD5 Message-Digest Algorithm),一種被廣泛使用的密碼雜湊函數(shù),可以產(chǎn)生出一個(gè)128位的散列值(hash value),用于確保信息傳輸完整一致。MD5的前身有MD2、MD3和MD4。

MD5功能

輸入任意長度的信息,經(jīng)過處理,輸出為128位的信息(數(shù)字指紋);
不同的輸入得到的不同的結(jié)果(唯一性);

MD5算法的特點(diǎn)

  1. 壓縮性:任意長度的數(shù)據(jù),算出的MD5值的長度都是固定的
  2. 容易計(jì)算:從原數(shù)據(jù)計(jì)算出MD5值很容易
  3. 抗修改性:對原數(shù)據(jù)進(jìn)行任何改動(dòng),修改一個(gè)字節(jié)生成的MD5值區(qū)別也會(huì)很大
  4. 強(qiáng)抗碰撞:已知原數(shù)據(jù)和MD5,想找到一個(gè)具有相同MD5值的數(shù)據(jù)(即偽造數(shù)據(jù))是非常困難的。

MD5算法是否可逆?

MD5不可逆的原因是其是一種散列函數(shù),使用的是hash算法,在計(jì)算過程中原文的部分信息是丟失了的。

MD5用途

  1. 防止被篡改:

    • 比如發(fā)送一個(gè)電子文檔,發(fā)送前,我先得到MD5的輸出結(jié)果a。然后在對方收到電子文檔后,對方也得到一個(gè)MD5的輸出結(jié)果b。如果a與b一樣就代表中途未被篡改。

    • 比如我提供文件下載,為了防止不法分子在安裝程序中添加木馬,我可以在網(wǎng)站上公布由安裝文件得到的MD5輸出結(jié)果。

    • SVN在檢測文件是否在CheckOut后被修改過,也是用到了MD5.

  2. 防止直接看到明文:

    • 現(xiàn)在很多網(wǎng)站在數(shù)據(jù)庫存儲(chǔ)用戶的密碼的時(shí)候都是存儲(chǔ)用戶密碼的MD5值。這樣就算不法分子得到數(shù)據(jù)庫的用戶密碼的MD5值,也無法知道用戶的密碼。(比如在UNIX系統(tǒng)中用戶的密碼就是以MD5(或其它類似的算法)經(jīng)加密后存儲(chǔ)在文件系統(tǒng)中。當(dāng)用戶登錄的時(shí)候,系統(tǒng)把用戶輸入的密碼計(jì)算成MD5值,然后再去和保存在文件系統(tǒng)中的MD5值進(jìn)行比較,進(jìn)而確定輸入的密碼是否正確。通過這樣的步驟,系統(tǒng)在并不知道用戶密碼的明碼的情況下就可以確定用戶登錄系統(tǒng)的合法性。這不但可以避免用戶的密碼被具有系統(tǒng)管理員權(quán)限的用戶知道,而且還在一定程度上增加了密碼被破解的難度。)
  3. 防止抵賴(數(shù)字簽名):

    • 這需要一個(gè)第三方認(rèn)證機(jī)構(gòu)。例如A寫了一個(gè)文件,認(rèn)證機(jī)構(gòu)對此文件用MD5算法產(chǎn)生摘要信息并做好記錄。若以后A說這文件不是他寫的,權(quán)威機(jī)構(gòu)只需對此文件重新產(chǎn)生摘要信息,然后跟記錄在冊的摘要信息進(jìn)行比對,相同的話,就證明是A寫的了。這就是所謂的“數(shù)字簽名”。

SHA-1

安全哈希算法(Secure Hash Algorithm)主要適用于數(shù)字簽名標(biāo)準(zhǔn)(Digital Signature Standard DSS)里面定義的數(shù)字簽名算法(Digital Signature Algorithm DSA)。對于長度小于2^64位的消息,SHA1會(huì)產(chǎn)生一個(gè)160位的消息摘要。當(dāng)接收到消息的時(shí)候,這個(gè)消息摘要可以用來驗(yàn)證數(shù)據(jù)的完整性。

SHA是美國國家安全局設(shè)計(jì)的,由美國國家標(biāo)準(zhǔn)和技術(shù)研究院發(fā)布的一系列密碼散列函數(shù)。

由于MD5和SHA-1于2005年被山東大學(xué)的教授王小云破解了,科學(xué)家們又推出了SHA224, SHA256, SHA384, SHA512,當(dāng)然位數(shù)越長,破解難度越大,但同時(shí)生成加密的消息摘要所耗時(shí)間也更長。目前最流行的是加密算法是SHA-256 .

MD5與SHA-1的比較

由于MD5與SHA-1均是從MD4發(fā)展而來,它們的結(jié)構(gòu)和強(qiáng)度等特性有很多相似之處,SHA-1與MD5的最大區(qū)別在于其摘要比MD5摘要長32 比特。對于強(qiáng)行攻擊,產(chǎn)生任何一個(gè)報(bào)文使之摘要等于給定報(bào)文摘要的難度:MD5是2128數(shù)量級的操作,SHA-1是2160數(shù)量級的操作。產(chǎn)生具有相同摘要的兩個(gè)報(bào)文的難度:MD5是264是數(shù)量級的操作,SHA-1 是280數(shù)量級的操作。因而,SHA-1對強(qiáng)行攻擊的強(qiáng)度更大。但由于SHA-1的循環(huán)步驟比MD5多80:64且要處理的緩存大160比特:128比特,SHA-1的運(yùn)行速度比MD5慢。

Python的 提供的相關(guān)模塊

用于加密相關(guān)的操作,3.x里代替了md5模塊和sha模塊,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

import hashlibm = hashlib.md5()m.update(b"Hello")m.update(b"It's me")print(m.digest())m.update(b"It's been a long time since last time we ...")print(m.digest()) #2進(jìn)制格式hashprint(len(m.hexdigest())) #16進(jìn)制格式hash'''def digest(self, *args, **kwargs): # real signature unknown    """ Return the digest value as a string of binary data. """    passdef hexdigest(self, *args, **kwargs): # real signature unknown    """ Return the digest value as a string of hexadecimal digits. """    pass'''import hashlib# ######## md5 ########hash = hashlib.md5()hash.update('admin')print(hash.hexdigest())# ######## sha1 ########hash = hashlib.sha1()hash.update('admin')print(hash.hexdigest())# ######## sha256 ########hash = hashlib.sha256()hash.update('admin')print(hash.hexdigest())# ######## sha384 ########hash = hashlib.sha384()hash.update('admin')print(hash.hexdigest())# ######## sha512 ########hash = hashlib.sha512()hash.update('admin')print(hash.hexdigest())
View Code

hashlib md5值的用法

#加入下面這個(gè)就可以password = input('請輸入密碼:')    m = hashlib.md5()    m.update(password.encode())    if m.hexdigest() == data1['password']:        print('登錄成功')
View Code

subprocess模塊

我們經(jīng)常需要通過Python去執(zhí)行一條系統(tǒng)命令或腳本,系統(tǒng)的shell命令是獨(dú)立于你的python進(jìn)程之外的,每執(zhí)行一條命令,就是發(fā)起一個(gè)新進(jìn)程,通過python調(diào)用系統(tǒng)命令或腳本的模塊在python2有os.system,

>>> os.system('uname -a')Darwin Alexs-MacBook-Pro.local 15.6.0 Darwin Kernel Version 15.6.0: Sun Jun  4 21:43:07 PDT 2017; root:xnu-3248.70.3~1/RELEASE_X86_64 x86_640

三種執(zhí)行命令的方法

  • subprocess.run(*popenargs, input=None, timeout=None, check=False, **kwargs) #官方推薦

  • subprocess.call(*popenargs, timeout=None, **kwargs) #跟上面實(shí)現(xiàn)的內(nèi)容差不多,另一種寫法

  • subprocess.Popen() #上面各種方法的底層封裝

run方法

#標(biāo)準(zhǔn)寫法subprocess.run(['df','-h'],stderr=subprocess.PIPE,stdout=subprocess.PIPE,check=True)#涉及到管道|的命令需要這樣寫subprocess.run('df -h|grep disk1',shell=True) #shell=True的意思是這條命令直接交給系統(tǒng)去執(zhí)行,不需要python負(fù)責(zé)解析
View Code

call()方法

#執(zhí)行命令,返回命令執(zhí)行狀態(tài) , 0 or 非0>>> retcode = subprocess.call(["ls", "-l"])#執(zhí)行命令,如果命令結(jié)果為0,就正常返回,否則拋異常>>> subprocess.check_call(["ls", "-l"])#接收字符串格式命令,返回元組形式,第1個(gè)元素是執(zhí)行狀態(tài),第2個(gè)是命令結(jié)果 >>> subprocess.getstatusoutput('ls /bin/ls')(0, '/bin/ls')#接收字符串格式命令,并返回結(jié)果>>> subprocess.getoutput('ls /bin/ls')'/bin/ls'#執(zhí)行命令,并返回結(jié)果,注意是返回結(jié)果,不是打印,下例結(jié)果返回給res>>> res=subprocess.check_output(['ls','-l'])>>> resb'total 0\ndrwxr-xr-x 12 alex staff 408 Nov 2 11:05 OldBoyCRM\n'
View Code

Popen()方法

常用參數(shù):

  • args:shell命令,可以是字符串或者序列類型(如:list,元組)
  • stdin, stdout, stderr:分別表示程序的標(biāo)準(zhǔn)輸入、輸出、錯(cuò)誤句柄
  • preexec_fn:只在Unix平臺(tái)下有效,用于指定一個(gè)可執(zhí)行對象(callable object),它將在子進(jìn)程運(yùn)行之前被調(diào)用
  • shell:同上
  • cwd:用于設(shè)置子進(jìn)程的當(dāng)前目錄
  • env:用于指定子進(jìn)程的環(huán)境變量。如果env = None,子進(jìn)程的環(huán)境變量將從父進(jìn)程中繼承。
a=subprocess.run('sleep 10',shell=True,stdout=subprocess.PIPE)a=subprocess.Popen('sleep 10',shell=True,stdout=subprocess.PIPE)

  

區(qū)別是Popen會(huì)在發(fā)起命令后立刻返回,而不等命令執(zhí)行結(jié)果。這樣的好處是什么呢?

如果你調(diào)用的命令或腳本 需要執(zhí)行10分鐘,你的主程序不需卡在這里等10分鐘,可以繼續(xù)往下走,干別的事情,每過一會(huì),通過一個(gè)什么方法來檢測一下命令是否執(zhí)行完成就好了。

Popen調(diào)用后會(huì)返回一個(gè)對象,可以通過這個(gè)對象拿到命令執(zhí)行結(jié)果或狀態(tài)等,該對象有以下方法

poll()

Check if child process has terminated. Returns returncode

wait()

Wait for child process to terminate. Returns returncode attribute.

terminate()終止所啟動(dòng)的進(jìn)程Terminate the process with SIGTERM

kill()?殺死所啟動(dòng)的進(jìn)程 Kill the process with SIGKILL

communicate()與啟動(dòng)的進(jìn)程交互,發(fā)送數(shù)據(jù)到stdin,并從stdout接收輸出,然后等待任務(wù)結(jié)束

>>> a = subprocess.Popen('python3 guess_age.py',stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE,shell=True)>>> a.communicate(b'22')(b'your guess:try bigger\n', b'')

send_signal(signal.xxx)發(fā)送系統(tǒng)信號

pid?拿到所啟動(dòng)進(jìn)程的進(jìn)程號

logging模塊

很多程序都有記錄日志的需求,并且日志中包含的信息即有正常的程序訪問日志,還可能有錯(cuò)誤、警告等信息輸出,python的logging模塊提供了標(biāo)準(zhǔn)的日志接口,你可以通過它存儲(chǔ)各種格式的日志,logging的日志可以分為?debug(), info(), warning(), error() and critical()5個(gè)級別,下面我們看一下怎么用。

#最簡單用法import logginglogging.warning("user [alex] attempted wrong password more than 3 times")logging.critical("server is down")
View Code
#輸出WARNING:root:user [alex] attempted wrong password more than 3 timesCRITICAL:root:server is down
View Code

如果想把日志寫到文件里,也很簡單

import logginglogging.basicConfig(filename='example.log',level=logging.INFO)logging.debug('This message should go to the log file')logging.info('So should this')logging.warning('And this, too')
View Code

其中下面這句中的level=loggin.INFO意思是,把日志紀(jì)錄級別設(shè)置為INFO,也就是說,只有比日志是INFO或比INFO級別更高的日志才會(huì)被紀(jì)錄文件里,在這個(gè)例子, 第一條日志是不會(huì)被紀(jì)錄的,如果希望紀(jì)錄debug的日志,那把日志級別改成DEBUG就行了.

?

自定義日志格式

?

感覺上面的日志格式忘記加上時(shí)間啦,日志不知道時(shí)間怎么行呢,下面就來加上!

import logginglogging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')logging.warning('is when this event was logged.')#輸出12/12/2010 11:46:36 AM is when this event was logged.
View Code

日志同時(shí)輸出到屏幕和文件

如果想同時(shí)把log打印在屏幕和文件日志里,就需要了解一點(diǎn)復(fù)雜的知識(shí) 了

Python 使用logging模塊記錄日志涉及四個(gè)主要類,使用官方文檔中的概括最為合適:

  • logger提供了應(yīng)用程序可以直接使用的接口;
  • handler將(logger創(chuàng)建的)日志記錄發(fā)送到合適的目的輸出;
  • filter提供了細(xì)度設(shè)備來決定輸出哪條日志記錄;
  • formatter決定日志記錄的最終輸出格式。

他們之間的關(guān)系是這樣的

?

logger

每個(gè)程序在輸出信息之前都要獲得一個(gè)Logger。Logger通常對應(yīng)了程序的模塊名,比如聊天工具的圖形界面模塊可以這樣獲得它的Logger:

LOG=logging.getLogger(”chat.gui”)

而核心模塊可以這樣:

LOG=logging.getLogger(”chat.kernel”)

還可以綁定handler和filters

Logger.setLevel(lel):指定最低的日志級別,低于lel的級別將被忽略。debug是最低的內(nèi)置級別,critical為最高Logger.addFilter(filt)、Logger.removeFilter(filt):添加或刪除指定的filterLogger.addHandler(hdlr)、Logger.removeHandler(hdlr):增加或刪除指定的handler

Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():可以設(shè)置的日志級別

handler

handler對象負(fù)責(zé)發(fā)送相關(guān)的信息到指定目的地。Python的日志系統(tǒng)有多種Handler可以使用。有些Handler可以把信息輸出到控制臺(tái),有些Handler可以把信息輸出到文件,還有些 Handler可以把信息發(fā)送到網(wǎng)絡(luò)上。如果覺得不夠用,還可以編寫自己的Handler。可以通過addHandler()方法添加多個(gè)多handler

Handler.setLevel(lel):指定被處理的信息級別,低于lel級別的信息將被忽略Handler.setFormatter():給這個(gè)handler選擇一個(gè)格式Handler.addFilter(filt)、Handler.removeFilter(filt):新增或刪除一個(gè)filter對象

  

每個(gè)Logger可以附加多個(gè)Handler。接下來我們就來介紹一些常用的Handler:

  1. logging.StreamHandler?使用這個(gè)Handler可以向類似與sys.stdout或者sys.stderr的任何文件對象(file object)輸出信息。
  2. logging.FileHandler?和StreamHandler 類似,用于向一個(gè)文件輸出日志信息。不過FileHandler會(huì)幫你打開這個(gè)文件
  3. logging.handlers.RotatingFileHandler

    這個(gè)Handler類似于上面的FileHandler,但是它可以管理文件大小。當(dāng)文件達(dá)到一定大小之后,它會(huì)自動(dòng)將當(dāng)前日志文件改名,然后創(chuàng)建 一個(gè)新的同名日志文件繼續(xù)輸出。比如日志文件是chat.log。當(dāng)chat.log達(dá)到指定的大小之后,RotatingFileHandler自動(dòng)把 文件改名為chat.log.1。不過,如果chat.log.1已經(jīng)存在,會(huì)先把chat.log.1重命名為chat.log.2。。。最后重新創(chuàng)建 chat.log,繼續(xù)輸出日志信息。它的函數(shù)是:

?

RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])

  其中filename和mode兩個(gè)參數(shù)和FileHandler一樣。

?

    • maxBytes用于指定日志文件的最大文件大小。如果maxBytes為0,意味著日志文件可以無限大,這時(shí)上面描述的重命名過程就不會(huì)發(fā)生。
    • backupCount用于指定保留的備份文件的個(gè)數(shù)。比如,如果指定為2,當(dāng)上面描述的重命名過程發(fā)生時(shí),原有的chat.log.2并不會(huì)被更名,而是被刪除。

logging.handlers.TimedRotatingFileHandler

這個(gè)Handler和RotatingFileHandler類似,不過,它沒有通過判斷文件大小來決定何時(shí)重新創(chuàng)建日志文件,而是間隔一定時(shí)間就 自動(dòng)創(chuàng)建新的日志文件。重命名的過程與RotatingFileHandler類似,不過新的文件不是附加數(shù)字,而是當(dāng)前時(shí)間。它的函數(shù)是:

TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])

  

其中filename參數(shù)和backupCount參數(shù)和RotatingFileHandler具有相同的意義。

interval是時(shí)間間隔。

when參數(shù)是一個(gè)字符串。表示時(shí)間間隔的單位,不區(qū)分大小寫。它有以下取值:

  • S 秒
  • M 分
  • H 小時(shí)
  • D 天
  • W 每星期(interval==0時(shí)代表星期一)
  • midnight 每天凌晨

formatter 組件

日志的formatter是個(gè)獨(dú)立的組件,可以跟handler組合

fh = logging.FileHandler("access.log")formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')fh.setFormatter(formatter) #把formmater綁定到fh上

  

filter 組件

如果你想對日志內(nèi)容進(jìn)行過濾,就可自定義一個(gè)filter

class IgnoreBackupLogFilter(logging.Filter):    """忽略帶db backup 的日志"""    def filter(self, record): #固定寫法        return   "db backup" not in record.getMessage()#注意filter函數(shù)會(huì)返加True or False,logger根據(jù)此值決定是否輸出此日志

  然后把這個(gè)filter添加到logger中

logger.addFilter(IgnoreBackupLogFilter())

  下面的日志就會(huì)把符合filter條件的過濾掉

logger.debug("test ....")logger.info("test info ....")logger.warning("start to run db backup job ....")logger.error("test error ....")

  一個(gè)同時(shí)輸出到屏幕、文件、帶filter的完成例子

import loggingclass IgnoreBackupLogFilter(logging.Filter):    """忽略帶db backup 的日志"""    def filter(self, record): #固定寫法        return   "db backup" not in record.getMessage()#console handlerch = logging.StreamHandler()ch.setLevel(logging.INFO)#file handlerfh = logging.FileHandler('mysql.log')#fh.setLevel(logging.WARNING)#formatterformatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')#bind formatter to chch.setFormatter(formatter)fh.setFormatter(formatter)logger = logging.getLogger("Mysql")logger.setLevel(logging.DEBUG) #logger 優(yōu)先級高于其它輸出途徑的#add handler   to logger instancelogger.addHandler(ch)logger.addHandler(fh)#add filterlogger.addFilter(IgnoreBackupLogFilter())logger.debug("test ....")logger.info("test info ....")logger.warning("start to run db backup job ....")logger.error("test error ....")
View Code

文件自動(dòng)截?cái)嗬?/p>

import loggingfrom logging import handlerslogger = logging.getLogger(__name__)log_file = "timelog.log"#fh = handlers.RotatingFileHandler(filename=log_file,maxBytes=10,backupCount=3)fh = handlers.TimedRotatingFileHandler(filename=log_file,when="S",interval=5,backupCount=3)formatter = logging.Formatter('%(asctime)s %(module)s:%(lineno)d %(message)s')fh.setFormatter(formatter)logger.addHandler(fh)logger.warning("test1")logger.warning("test12")logger.warning("test13")logger.warning("test14")
View Code

re模塊

正則表達(dá)式就是字符串的匹配規(guī)則,在多數(shù)編程語言里都有相應(yīng)的支持,python里對應(yīng)的模塊是re

常用的表達(dá)式規(guī)則

'.'     默認(rèn)匹配除\n之外的任意一個(gè)字符,若指定flag DOTALL,則匹配任意字符,包括換行'^'     匹配字符開頭,若指定flags MULTILINE,這種也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)'$'     匹配字符結(jié)尾, 若指定flags MULTILINE ,re.search('foo.$','foo1\nfoo2\n',re.MULTILINE).group() 會(huì)匹配到foo1'*'     匹配*號前的字符0次或多次, re.search('a*','aaaabac')  結(jié)果'aaaa'' '     匹配前一個(gè)字符1次或多次,re.findall("ab ","ab cd abb bba") 結(jié)果['ab', 'abb']'?'     匹配前一個(gè)字符1次或0次 ,re.search('b?','alex').group() 匹配b 0次'{m}'   匹配前一個(gè)字符m次 ,re.search('b{3}','alexbbbs').group()  匹配到'bbb''{n,m}' 匹配前一個(gè)字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 結(jié)果'abb', 'ab', 'abb']'|'     匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 結(jié)果'ABC''(...)' 分組匹配, re.search("(abc){2}a(123|45)", "abcabca456c").group() 結(jié)果為'abcabca45''\A'    只從字符開頭匹配,re.search("\Aabc","alexabc") 是匹配不到的,相當(dāng)于re.match('abc',"alexabc") 或^'\Z'    匹配字符結(jié)尾,同$ '\d'    匹配數(shù)字0-9'\D'    匹配非數(shù)字'\w'    匹配[A-Za-z0-9]'\W'    匹配非[A-Za-z0-9]'s'     匹配空白字符、\t、\n、\r , re.search("\s ","ab\tc1\n3").group() 結(jié)果 '\t''(?P<name>...)' 分組匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 結(jié)果{'province': '3714', 'city': '81', 'birthday': '1993'}

re的匹配語法有以下幾種

  • re.match 從頭開始匹配
  • re.search 匹配包含
  • re.findall 把所有匹配到的字符放到以列表中的元素返回
  • re.split 以匹配到的字符當(dāng)做列表分隔符
  • re.sub 匹配字符并替換
  • re.fullmatch 全部匹配

軟件開發(fā)目錄規(guī)范

Foo/|-- bin/|   |-- foo||-- foo/|   |-- tests/|   |   |-- __init__.py|   |   |-- test_main.py|   ||   |-- __init__.py|   |-- main.py||-- docs/|   |-- conf.py|   |-- abc.rst||-- setup.py|-- requirements.txt|-- README

  

簡要解釋一下:

  • bin/: 存放項(xiàng)目的一些可執(zhí)行文件,當(dāng)然你可以起名script/之類的也行。
  • foo/: 存放項(xiàng)目的所有源代碼。(1) 源代碼中的所有模塊、包都應(yīng)該放在此目錄。不要置于頂層目錄。(2) 其子目錄tests/存放單元測試代碼; (3) 程序的入口最好命名為main.py。
  • docs/: 存放一些文檔。
  • setup.py: 安裝、部署、打包的腳本。
  • requirements.txt: 存放軟件依賴的外部Python包列表。
  • README: 項(xiàng)目說明文件。

conf 存配置文件的,(賬戶數(shù)據(jù)、日志的文件名或者格式,這些用戶可以配置的;)

?

來源:http://www.icode9.com/content-4-27711.html
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
想做Python開發(fā),這14種常用Python模塊,你必須知道!
5 模塊
python之ATM
python知識(shí)鞏固 | 自定義日志模塊封裝,將日志格式化打印到控制臺(tái)或是輸出到文件?
Python中的logger和handler到底是個(gè)什么鬼
python包和logging日志的相關(guān)介紹
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服