直接import導入node
用from xxx import xxx,xxx,xxx,xxx 導入 一個或多個python
from module.xx.xx import xx as rename 重命名,模塊名太長能夠重命名mysql
from module.xx.xx import * 一層一層目錄裏面進去 導入模塊,後面可使用*號linux
能夠不用重複敲前綴名,可是不推薦使用這種.會產生重名問題git
注意:模塊一旦被調用,即至關於執行了另一個py文件裏的代碼正則表達式
建立一個.py文件,就能夠稱之爲模塊,就能夠在另一個程序裏導入算法
發現,本身寫的模塊只能在當前路徑下的程序裏才能導入,換一個目錄再導入本身的模塊就報錯說找不到了, 這是爲何?sql
這與導入路徑有關shell
import sys print(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']
python解釋器會按照列表順序去依次到每一個目錄下去匹配你要導入的模塊名,只要在一個目錄下匹配到了該模塊名,就馬上導入,再也不繼續日後找。
注意列表第一個元素爲空,即表明當前目錄,因此你本身定義的模塊在當前目錄會被優先導入。
https://pypi.python.org/pypi 是python的開源模塊庫,截止2017年9.30日 ,已經收錄了118170個來自全世界python開發者貢獻的模塊,幾乎涵蓋了你想用python作的任何事情。 事實上每一個python開發者,只要註冊一個帳號就能夠往這個平臺上傳你本身的模塊,這樣全世界的開發者均可以容易的下載並使用你的模塊。
直接在上面這個頁面上點download,下載後,解壓並進入目錄,執行如下命令 完成安裝
編譯源碼 python setup.py build 安裝源碼 python setup.py install
直接經過pip安裝
pip3 install paramiko #paramiko 是模塊名
pip命令會自動下載模塊包並完成安裝。
軟件通常會被自動安裝你python安裝目錄的這個子目錄裏
/your_python_install_path/3.6/lib/python3.6/site-packages
pip命令默認會鏈接在國外的python官方服務器下載,速度比較慢,你還可使用國內的豆瓣源,數據會按期同步國外官網,速度快好多
sudo pip install -i http://pypi.douban.com/simple/ alex_sayhi --trusted-host pypi.douban.com #alex_sayhi是模塊名
下載後,直接導入使用就能夠,跟自帶的模塊調用方法無差,演示一個鏈接linux執行命令的模塊
#coding:utf-8 import paramiko ssh = 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(); 執行命令 - 經過用戶名和密碼鏈接服務器
當你的模塊文件愈來愈多,就須要對模塊文件進行劃分,好比把負責跟數據庫交互的都放一個文件夾,把與頁面交互相關的放一個文件夾,
. └── my_proj ├── crm #代碼目錄 │ ├── admin.py │ ├── apps.py │ ├── models.py │ ├── tests.py │ └── views.py ├── manage.py └── my_proj #配置文件目錄 ├── settings.py ├── urls.py └── wsgi.py
像上面這樣,一個文件夾管理多個模塊文件,這個文件夾就被稱爲包
那不一樣包之間的模塊互相導入呢?
包就是文件夾,但該文件夾下必須存在 __init__.py 文件, 該文件的內容能夠爲空。__int__.py用於標識當前文件夾是一個包。
注意,在python3裏,即便目錄下沒__int__.py文件也能建立成功,猜應該是解釋器優化所致,但建立包仍是要記得加上這個文件 吧。
在涉及到相對導入時,package所對應的文件夾必須正確的被python解釋器視做package,而不是普通文件夾。不然因爲不被視做package,沒法利用package之間的嵌套關係實現python中包的相對導入。
文件夾被python解釋器視做package須要知足兩個條件:
注:雖然python支持相對導入,但對模塊間的路徑關係要求比較嚴格,處理不當就容易出錯,so並不建議在項目裏常用。
在日常的代碼中,咱們經常須要與時間打交道。在Python中,與時間處理有關的模塊就包括:time,datetime,calendar(不多用,不講),下面分別來介紹。
在開始以前,首先要說明幾點:
1、在Python中,一般有這幾種方式來表示時間:
2、幾個定義
UTC(Coordinated Universal Time,世界協調時)亦即格林威治天文時間,世界標準時間。在中國爲UTC+8。DST(Daylight Saving Time)即夏令時。
時間戳(timestamp)的方式:一般來講,時間戳表示的是從1970年1月1日00:00:00開始按秒計算的偏移量。咱們運行「type(time.time())」,返回的是float類型。
元組(struct_time)方式:struct_time元組共有9個元素,返回struct_time的函數主要有gmtime(),localtime(),strptime()。下面列出這種方式元組中的幾個元素:
索引(Index) 屬性(Attribute) 值(Values) 0 tm_year(年) 好比2011 1 tm_mon(月) 1 - 12 2 tm_mday(日) 1 - 31 3 tm_hour(時) 0 - 23 4 tm_min(分) 0 - 59 5 tm_sec(秒) 0 - 61 6 tm_wday(weekday) 0 - 6(0表示週日) 7 tm_yday(一年中的第幾天) 1 - 366 8 tm_isdst(是不是夏令時) 默認爲-1
| 字符串轉時間格式對應表 |
---------- | Meaning | Notes |
---|---|---|
%a |
Locale’s abbreviated weekday name. | 周縮寫 |
%A |
Locale’s full weekday name. | 周全稱 |
%b |
Locale’s abbreviated month name. | 月份簡寫 |
%B |
Locale’s full month name. | 月份全稱 |
%c |
Locale’s appropriate date and time representation. | 'Fri May 4 10:51:37 2018' |
%d |
Day of the month as a decimal number [01,31]. | [01,31]格式輸出本月中的某日 |
%H |
Hour (24-hour clock) as a decimal number [00,23]. | 24小時制 |
%I |
Hour (12-hour clock) as a decimal number [01,12]. | 12小時制 |
%j |
Day of the year as a decimal number [001,366]. | 一年中的第幾天 |
%m |
Month as a decimal number [01,12]. | [01,12]幾月 |
%M |
Minute as a decimal number [00,59]. | [00,59]第幾分鐘 |
%p |
Locale’s equivalent of either AM or PM. | (1)AM or PM |
%S |
Second as a decimal number [00,61]. | (2)第幾秒 |
%U |
Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0. | (3)今年第幾周,星期天爲一週開始 |
%w |
Weekday as a decimal number [0(Sunday),6]. | [0(Sunday),6]本週第幾天 |
%W |
Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0. | (3)今年第幾周,星期一爲一週開始 |
%x |
Locale’s appropriate date representation. | '05/04/18'格式時間 |
%X |
Locale’s appropriate time representation. | 10:55:46'格式時間 |
%y |
Year without century as a decimal number [00,99]. | 年份簡寫 |
%Y |
Year with century as a decimal number. | 年份全稱 |
%z |
Time zone offset indicating a positive or negative time difference from UTC/GMT of the form +HHMM or -HHMM, where H represents decimal hour digits and M represents decimal minute digits [-23:59, +23:59]. | 時區 |
%Z |
Time zone name (no characters if no time zone exists). | |
%% |
A literal '%' character.%轉義 |
最後爲了容易記住轉換關係,看下圖
相比於time模塊,datetime模塊的接口則更直觀、更容易調用
datetime模塊定義了下面這幾個類:
咱們須要記住的方法僅如下幾個:
d.timestamp(),d.today(), d.year,d.timetuple()等方法能夠調用
2.datetime.date.fromtimestamp(322222) 把一個時間戳轉爲datetime日期類型
3.時間運算
>>> datetime.datetime.now() datetime.datetime(2017, 10, 1, 12, 53, 11, 821218) >>> datetime.datetime.now() + datetime.timedelta(4) #當前時間 +4天 datetime.datetime(2017, 10, 5, 12, 53, 35, 276589) >>> datetime.datetime.now() + datetime.timedelta(hours=4) #當前時間+4小時 datetime.datetime(2017, 10, 1, 16, 53, 42, 876275)
4.時間替換
>>> d.replace(year=2999,month=11,day=30) datetime.date(2999, 11, 30)
程序中有不少地方須要用到隨機字符,好比登陸網站的隨機驗證碼,經過random模塊能夠很容易生成隨機字符串
>>> random.randrange(1,10) #返回1-10之間的一個隨機數,不包括10 >>> random.randint(1,10) #返回1-10之間的一個隨機數,包括10 >>> random.randrange(0, 100, 2) #隨機選取0到100間的偶數 >>> random.random() #返回一個隨機浮點數 >>> random.choice('abce3#$@1') #返回一個給定數據集合中的隨機字符 '#' >>> random.sample('abcdefghij',3) #從多個字符中選取特定數量的字符 ['a', 'd', 'b'] #生成隨機字符串 >>> 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]
獲得當前工做目錄,即當前Python腳本工做的目錄路徑: os.getcwd() 返回指定目錄下的全部文件和目錄名:os.listdir() 函數用來刪除一個文件:os.remove() 刪除多個目錄:os.removedirs(r「c:\python」) 檢驗給出的路徑是不是一個文件:os.path.isfile() 檢驗給出的路徑是不是一個目錄:os.path.isdir() 判斷是不是絕對路徑:os.path.isabs() 檢驗給出的路徑是否真地存:os.path.exists() 返回一個路徑的目錄名和文件名:os.path.split() e.g os.path.split('/home/swaroop/byte/code/poem.txt') 結果:('/home/swaroop/byte/code', 'poem.txt') 分離擴展名:os.path.splitext() e.g os.path.splitext('/usr/local/test.py') 結果:('/usr/local/test', '.py') 獲取路徑名:os.path.dirname() 得到絕對路徑: os.path.abspath() 獲取文件名:os.path.basename() 運行shell命令: os.system() 讀取操做系統環境變量HOME的值:os.getenv("HOME") 返回操做系統全部的環境變量: os.environ 設置系統環境變量,僅程序運行時有效:os.environ.setdefault('HOME','/home/alex') 給出當前平臺使用的行終止符:os.linesep Windows使用'\r\n',Linux and MAC使用'\n' 指示你正在使用的平臺:os.name 對於Windows,它是'nt',而對於Linux/Unix用戶,它是'posix' 重命名:os.rename(old, new) 建立多級目錄:os.makedirs(r「c:\python\test」) 建立單個目錄:os.mkdir(「test」) 獲取文件屬性:os.stat(file) 修改文件權限與時間戳:os.chmod(file) 獲取文件大小:os.path.getsize(filename) 結合目錄名與文件名:os.path.join(dir,filename) 改變工做目錄到dirname: os.chdir(dirname) 獲取當前終端的大小: os.get_terminal_size() 殺死進程: os.kill(10884,signal.SIGKILL)
sys.argv # 命令行參數List,第一個元素是程序自己路徑 sys.exit(n) # 退出程序,正常退出時exit(0) sys.version # 獲取Python解釋程序的版本信息 sys.maxsize # 最大的Int值 sys.path # 返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值 sys.platform # 返回操做系統平臺名稱 sys.stdout.write('please:') #標準輸出 , 引出進度條的例子, 注,在py3上不行,能夠用print代替 val = sys.stdin.readline()[:-1] #標準輸入 sys.getrecursionlimit() #獲取最大遞歸層數 sys.setrecursionlimit(1200) #設置最大遞歸層數 sys.getdefaultencoding() #獲取解釋器默認編碼 sys.getfilesystemencoding #獲取內存數據存到文件裏的默認編碼
高級的 文件、文件夾、壓縮包 處理模塊
shutil.copyfileobj(fsrc, fdst[, length]) 將文件內容拷貝到另外一個文件中
import shutil shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))
shutil.copyfile(src, dst) 拷貝文件
shutil.copyfile('f1.log', 'f2.log') #目標文件無需存在
shutil.copymode(src, dst) 僅拷貝權限。內容、組、用戶均不變
shutil.copymode('f1.log', 'f2.log') #目標文件必須存在
shutil.copystat(src, dst) 僅拷貝狀態的信息,包括:mode bits, atime, mtime, flags
shutil.copystat('f1.log', 'f2.log') #目標文件必須存在
shutil.copy(src, dst) 拷貝文件和權限
import shutil shutil.copy('f1.log', 'f2.log')
shutil.copy2(src, dst) 拷貝文件和狀態信息
import shutil shutil.copy2('f1.log', 'f2.log')
shutil.ignore_patterns(*patterns) shutil.copytree(src, dst, symlinks=False, ignore=None) 遞歸的去拷貝文件夾
import shutil shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目標目錄不能存在,注意對folder2目錄父級目錄要有可寫權限,ignore的意思是排除
shutil.rmtree(path[, ignore_errors[, onerror]]) 遞歸的去刪除文件
import shutil shutil.rmtree('folder1')
shutil.move(src, dst) 遞歸的去移動文件,它相似mv命令,其實就是重命名。
import shutil shutil.move('folder1', 'folder3')
shutil.make_archive(base_name, format,...) 建立壓縮包並返回文件路徑,例如:zip、tar 建立壓縮包並返回文件路徑,例如:zip、tar
如 data_bak =>保存至當前路徑 如:/tmp/data_bak =>保存至/tmp/
#將 /data 下的文件打包放置當前程序目錄 import shutil ret = shutil.make_archive("data_bak", 'gztar', root_dir='/data') #將 /data下的文件打包放置 /tmp/目錄 import shutil ret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data')
shutil 對壓縮包的處理是調用 ZipFile 和 TarFile 兩個模塊來進行的,詳細: 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()
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()
什麼叫序列化?
用於序列化的兩個模塊
Json模塊提供了四個功能:dumps、dump、loads、load
pickle模塊提供了四個功能:dumps、dump、loads、load
JSON:
優勢:跨語言、體積小
缺點:只能支持int\str\list\tuple\dict
Pickle:
優勢:專爲python設計,支持python全部的數據類型
缺點:只能在python中使用,存儲數據佔空間大
json.dumps json.loads
只是把數據類型轉換成字符串存到內存裏的意義?
- 把你的內存數據經過網絡共享給遠程其餘人
- 定義了不通語言之間的交互規則
- 純文本,壞處是不能共享複雜的數據類型
- xml,壞處是佔用空間大
- json,簡單,可讀性好
shelve模塊是一個簡單的k,v將內存數據經過文件持久化的模塊,能夠持久化任何pickle可支持的python數據格式
序列化:
import shelve f = shelve.open('shelve_test') # 打開一個文件 names = ["alex", "rain", "test"] info = {'name':'alex','age':22} f["names"] = names # 持久化列表 f['info_dic'] = info f.close()
反序列化:
import shelve d = shelve.open('shelve_test') # 打開一個文件 print(d['names']) print(d['info_dic']) #del d['test'] #還能夠刪除
能夠直接刪除,增長.
修改的話必須是對整個value值的從新賦值,而不是取出value值中的某一個元素(好比value是一個列表,取列表某一個元素進行更改是不行的,只能從新對這個列表value賦值)去更改賦值.
xml是實現不一樣語言或程序之間進行數據交換的協議,跟json差很少,但json使用起來更簡單,不過,古時候,在json還沒誕生的黑暗年代,你們只能選擇用xml呀,至今不少傳統公司如金融行業的不少系統的接口還主要是xml。
xml的格式以下,就是經過<>節點來區別數據結構的:
<?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>
xml協議在各個語言裏的都 是支持的,在python中能夠用如下模塊操做xml
import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml") root = tree.getroot() print(root.tag) #遍歷xml文檔 for child in root: print(child.tag, child.attrib) for i in child: print(i.tag,i.text) #只遍歷year 節點 for node in root.iter('year'): print(node.tag,node.text)
修改和刪除xml文檔內容
import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml") root = tree.getroot() #修改 for node in root.iter('year'): new_year = int(node.text) + 1 node.text = str(new_year) node.set("updated","yes") tree.write("xmltest.xml") #刪除node for country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country) tree.write('output.xml')
本身建立xml文檔
import xml.etree.ElementTree as ET new_xml = ET.Element("namelist") name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"}) age = ET.SubElement(name,"age",attrib={"checked":"no"}) sex = ET.SubElement(name,"sex") sex.text = '33' 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) #打印生成的格式
此模塊用於生成和修改常見配置文檔,當前模塊的名稱在 python 3.x 版本中變動爲 configparser。
來看一個好多軟件的常見配置文件格式以下
[DEFAULT] ServerAliveInterval = 45 Compression = yes CompressionLevel = 9 ForwardX11 = yes [bitbucket.org] User = hg [topsecret.server.com] Port = 50022 ForwardX11 = no
解析配置文件
>>> import configparser # 導入模塊 >>> config = configparser.ConfigParser() #實例化(生成對象) >>> config.sections() #調用sections方法 [] >>> config.read('example.ini') # 讀配置文件(注意文件路徑) ['example.ini'] >>> config.sections() #調用sections方法(默認不會讀取default) ['bitbucket.org', 'topsecret.server.com'] >>> 'bitbucket.org' in config #判斷元素是否在sections列表內 True >>> 'bytebong.com' in config False >>> 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循環 bitbucket.org 字典的key ... user compressionlevel serveraliveinterval compression forwardx11 >>> config['bitbucket.org']['ForwardX11'] 'yes'
其它增刪改查語法
[group1] # 支持的兩種分隔符「=」, 「:」 k1 = v1 k2:v2 [group2] k1 = v1 import ConfigParser config = ConfigParser.ConfigParser() config.read('i.cfg') # ########## 讀 ########## #secs = config.sections() #print(secs) #options = config.options('group2') # 獲取指定section的keys #print(options) #item_list = config.items('group2') # 獲取指定 section 的 keys & values ,key value 以元組的形式 #print(item_list) #val = config.get('group1','key') # 獲取指定的key 的value #val = config.getint('group1','key') # ########## 改寫 ########## #sec = config.remove_section('group1') # 刪除section 並返回狀態(true, false) #config.write(open('i.cfg', "w")) # 對應的刪除操做要寫入文件纔會生效 #sec = config.has_section('wupeiqi') #sec = config.add_section('wupeiqi') #config.write(open('i.cfg', "w")) #
Hash,通常翻譯作「散列」,也有直接音譯爲」哈希」的,就是把任意長度的輸入(又叫作預映射,pre-image),經過散列算法,變換成固定長度的輸出,該輸出就是散列值。這種轉換是一種壓縮映射,也就是,散列值的空間一般遠小於輸入的空間,不一樣的輸入可能會散列成相同的輸出,而不可能從散列值來惟一的肯定輸入值。
簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數。
HASH主要用於信息安全領域中加密算法,他把一些不一樣長度的信息轉化成雜亂的128位的編碼裏,叫作HASH值.也能夠說,hash就是找到一種數據內容和數據存放地址之間的映射關係
什麼是MD5算法
MD5訊息摘要演算法(英語:MD5 Message-Digest Algorithm),一種被普遍使用的密碼雜湊函數,能夠產生出一個128位的散列值(hash value),用於確保信息傳輸完整一致。MD5的前身有MD二、MD3和MD4。
MD5功能
輸入任意長度的信息,通過處理,輸出爲128位的信息(數字指紋); 不一樣的輸入獲得的不一樣的結果(惟一性);
MD5算法的特色
MD5算法是否可逆?
MD5不可逆的緣由是其是一種散列函數,使用的是hash算法,在計算過程當中原文的部分信息是丟失了的。
MD5用途
安全哈希算法(Secure Hash Algorithm)主要適用於數字簽名標準(Digital Signature Standard DSS)裏面定義的數字簽名算法(Digital Signature Algorithm DSA)。對於長度小於2^64位的消息,SHA1會產生一個160位的消息摘要。當接收到消息的時候,這個消息摘要能夠用來驗證數據的完整性。
SHA是美國國家安全局設計的,由美國國家標準和技術研究院發佈的一系列密碼散列函數。
因爲MD5和SHA-1於2005年被山東大學的教授王小云破解了,科學家們又推出了SHA224, SHA256, SHA384, SHA512,固然位數越長,破解難度越大,但同時生成加密的消息摘要所耗時間也更長。目前最流行的是加密算法是SHA-256 .
因爲MD5與SHA-1均是從MD4發展而來,它們的結構和強度等特性有不少類似之處,SHA-1與MD5的最大區別在於其摘要比MD5摘要長32 比特。對於強行攻擊,產生任何一個報文使之摘要等於給定報文摘要的難度:MD5是2128數量級的操做,SHA-1是2160數量級的操做。產生具備相同摘要的兩個報文的難度:MD5是264是數量級的操做,SHA-1 是280數量級的操做。於是,SHA-1對強行攻擊的強度更大。但因爲SHA-1的循環步驟比MD5多80:64且要處理的緩存大160比特:128比特,SHA-1的運行速度比MD5慢。
用於加密相關的操做,3.x裏代替了md5模塊和sha模塊,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
import hashlib m = 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進制格式hash print(len(m.hexdigest())) #16進制格式hash ''' def digest(self, *args, **kwargs): # real signature unknown """ Return the digest value as a string of binary data. """ pass def 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())
三種執行命令的方法
Run command with arguments and return a CompletedProcess instance.The returned instance will have attributes args, returncode, stdout and stderr. By default, stdout and stderr are not captured, and those attributes will be None. Pass stdout=PIPE and/or stderr=PIPE in order to capture them.
If check is True and the exit code was non-zero, it raises a CalledProcessError. The CalledProcessError object will have the return code in the returncode attribute, and output & stderr attributes if those streams were captured.
If timeout is given, and the process takes too long, a TimeoutExpired exception will be raised.
The other arguments are the same as for the Popen constructor.
標準寫法
subprocess.run(['df','-h'],stderr=subprocess.PIPE,stdout=subprocess.PIPE,check=True)
涉及到管道|的命令須要這樣寫
subprocess.run('df -h|grep disk1',shell=True) #shell=True的意思是這條命令直接交給系統去執行,不須要python負責解析
#執行命令,返回命令執行狀態 , 0 or 非0 >>> retcode = subprocess.call(["ls", "-l"]) #執行命令,若是命令結果爲0,就正常返回,不然拋異常 >>> subprocess.check_call(["ls", "-l"]) 0 #接收字符串格式命令,返回元組形式,第1個元素是執行狀態,第2個是命令結果 >>> subprocess.getstatusoutput('ls /bin/ls') (0, '/bin/ls') #接收字符串格式命令,並返回結果 >>> subprocess.getoutput('ls /bin/ls') '/bin/ls' #執行命令,並返回結果,注意是返回結果,不是打印,下例結果返回給res >>> res=subprocess.check_output(['ls','-l']) >>> res b'total 0\ndrwxr-xr-x 12 alex staff 408 Nov 2 11:05 OldBoyCRM\n'
經常使用參數:
下面這2條語句執行會有什麼區別?
a=subprocess.run('sleep 10',shell=True,stdout=subprocess.PIPE) a=subprocess.Popen('sleep 10',shell=True,stdout=subprocess.PIPE)
區別是Popen會在發起命令後馬上返回,而不等命令執行結果。這樣的好處是什麼呢?
若是你調用的命令或腳本 須要執行10分鐘,你的主程序不需卡在這裏等10分鐘,能夠繼續往下走,幹別的事情,每過一會,經過一個什麼方法來檢測一下命令是否執行完成就行了。
Popen調用後會返回一個對象,能夠經過這個對象拿到命令執行結果或狀態等,該對象有如下方法
poll()
Check if child process has terminated. Returns returncode
wait()
Wait for child process to terminate. Returns returncode attribute.
terminate()
終止所啓動的進程Terminate the process with SIGTERM
kill()
殺死所啓動的進程 Kill the process with SIGKILL
communicate()
與啓動的進程交互,發送數據到stdin,並從stdout接收輸出,而後等待任務結束
>>> 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)
發送系統信號
pid
拿到所啓動進程的進程號
不少程序都有記錄日誌的需求,而且日誌中包含的信息即有正常的程序訪問日誌,還可能有錯誤、警告等信息輸出,python的logging模塊提供了標準的日誌接口,你能夠經過它存儲各類格式的日誌,logging的日誌能夠分爲 debug(), info(), warning(), error() and critical()
5個級別,下面咱們看一下怎麼用。
import logging logging.warning("user [alex] attempted wrong password more than 3 times") logging.critical("server is down")
輸出
WARNING:root:user [alex] attempted wrong password more than 3 times CRITICAL:root:server is down
看一下這幾個日誌級別分別表明什麼意思
Level | When it’s used |
---|---|
DEBUG |
Detailed information, typically of interest only when diagnosing problems. |
INFO |
Confirmation that things are working as expected. |
WARNING |
An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected. |
ERROR |
Due to a more serious problem, the software has not been able to perform some function. |
CRITICAL |
A serious error, indicating that the program itself may be unable to continue running. |
import logging logging.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')
其中下面這句中的level=loggin.INFO意思是,把日誌紀錄級別設置爲INFO,也就是說,只有比日誌是INFO或比INFO級別更高的日誌纔會被紀錄到文件裏,在這個例子, 第一條日誌是不會被紀錄的,若是但願紀錄debug的日誌,那把日誌級別改爲DEBUG就好了。
logging.basicConfig(filename='example.log',level=logging.INFO)
感受上面的日誌格式忘記加上時間啦,日誌不知道時間怎麼行呢,下面就來加上!
import logging logging.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.
除了加時間,還能夠自定義一大堆格式,下表就是全部支持的格式
%(name)s | Logger的名字 |
---|---|
%(levelno)s | 數字形式的日誌級別 |
%(levelname)s | 文本形式的日誌級別 |
%(pathname)s | 調用日誌輸出函數的模塊的完整路徑名,可能沒有 |
%(filename)s | 調用日誌輸出函數的模塊的文件名 |
%(module)s | 調用日誌輸出函數的模塊名 |
%(funcName)s | 調用日誌輸出函數的函數名 |
%(lineno)d | 調用日誌輸出函數的語句所在的代碼行 |
%(created)f | 當前時間,用UNIX標準的表示時間的浮 點數表示 |
%(relativeCreated)d | 輸出日誌信息時的,自Logger建立以 來的毫秒數 |
%(asctime)s | 字符串形式的當前時間。默認格式是 「2003-07-08 16:49:45,896」。逗號後面的是毫秒 |
%(thread)d | 線程ID。可能沒有 |
%(threadName)s | 線程名。可能沒有 |
%(process)d | 進程ID。可能沒有 |
%(message)s | 用戶輸出的消息 |
若是想同時把log打印在屏幕和文件日誌裏,就須要瞭解一點複雜的知識 了
Python 使用logging模塊記錄日誌涉及四個主要類,使用官方文檔中的歸納最爲合適:
每一個程序在輸出信息以前都要得到一個Logger。Logger一般對應了程序的模塊名,好比聊天工具的圖形界面模塊能夠這樣得到它的Logger:
LOG=logging.getLogger(」chat.gui」)
而核心模塊能夠這樣:
LOG=logging.getLogger(」chat.kernel」)
還能夠綁定handler和filters
Logger.setLevel(lel):指定最低的日誌級別,低於lel的級別將被忽略。debug是最低的內置級別,critical爲最高 Logger.addFilter(filt)、Logger.removeFilter(filt):添加或刪除指定的filter Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增長或刪除指定的handler
Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():能夠設置的日誌級別
handler對象負責發送相關的信息到指定目的地。Python的日誌系統有多種Handler可使用。有些Handler能夠把信息輸出到控制檯,有些Handler能夠把信息輸出到文件,還有些 Handler能夠把信息發送到網絡上。若是以爲不夠用,還能夠編寫本身的Handler。能夠經過addHandler()方法添加多個多handler
Handler.setLevel(lel):指定被處理的信息級別,低於lel級別的信息將被忽略 Handler.setFormatter():給這個handler選擇一個格式 Handler.addFilter(filt)、Handler.removeFilter(filt):新增或刪除一個filter對象
每一個Logger能夠附加多個Handler。接下來咱們就來介紹一些經常使用的Handler:
logging.StreamHandler 使用這個Handler能夠向相似與sys.stdout或者sys.stderr的任何文件對象(file object)輸出信息。
logging.FileHandler 和StreamHandler 相似,用於向一個文件輸出日誌信息。不過FileHandler會幫你打開這個文件
logging.handlers.RotatingFileHandler
這個Handler相似於上面的FileHandler,可是它能夠管理文件大小。當文件達到必定大小以後,它會自動將當前日誌文件更名,而後建立 一個新的同名日誌文件繼續輸出。好比日誌文件是chat.log。當chat.log達到指定的大小以後,RotatingFileHandler自動把 文件更名爲chat.log.1。不過,若是chat.log.1已經存在,會先把chat.log.1重命名爲chat.log.2。。。最後從新建立 chat.log,繼續輸出日誌信息。它的函數是:
RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])
其中filename和mode兩個參數和FileHandler同樣。
logging.handlers.TimedRotatingFileHandler
這個Handler和RotatingFileHandler相似,不過,它沒有經過判斷文件大小來決定什麼時候從新建立日誌文件,而是間隔必定時間就 自動建立新的日誌文件。重命名的過程與RotatingFileHandler相似,不過新的文件不是附加數字,而是當前時間。它的函數是:
TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])
其中filename參數和backupCount參數和RotatingFileHandler具備相同的意義。
interval
是時間間隔。
when
參數是一個字符串。表示時間間隔的單位,不區分大小寫。它有如下取值:
日誌的formatter是個獨立的組件,能夠跟handler組合
fh = logging.FileHandler("access.log") formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) #把formmater綁定到fh上
若是你想對日誌內容進行過濾,就可自定義一個filter
class IgnoreBackupLogFilter(logging.Filter): """忽略帶db backup 的日誌""" def filter(self, record): #固定寫法 return "db backup" not in record.getMessage()
注意filter函數會返加True or False,logger根據此值決定是否輸出此日誌
而後把這個filter添加到logger中
logger.addFilter(IgnoreBackupLogFilter())
下面的日誌就會把符合filter條件的過濾掉
logger.debug("test ....") logger.info("test info ....") logger.warning("start to run db backup job ....") logger.error("test error ....")
一個同時輸出到屏幕、文件、帶filter的完成例子
import logging class IgnoreBackupLogFilter(logging.Filter): """忽略帶db backup 的日誌""" def filter(self, record): #固定寫法 return "db backup" not in record.getMessage() #console handler ch = logging.StreamHandler() ch.setLevel(logging.INFO) #file handler fh = logging.FileHandler('mysql.log') #fh.setLevel(logging.WARNING) #formatter formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') #bind formatter to ch ch.setFormatter(formatter) fh.setFormatter(formatter) logger = logging.getLogger("Mysql") logger.setLevel(logging.DEBUG) #logger 優先級高於其它輸出途徑的 #add handler to logger instance logger.addHandler(ch) logger.addHandler(fh) #add filter logger.addFilter(IgnoreBackupLogFilter()) logger.debug("test ....") logger.info("test info ....") logger.warning("start to run db backup job ....") logger.error("test error ....")
文件自動截斷例子
import logging from logging import handlers logger = 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")
正則表達式就是字符串的匹配規則,在多數編程語言裏都有相應的支持,python裏對應的模塊是re
'.' 默認匹配除\n以外的任意一個字符,若指定flag DOTALL,則匹配任意字符,包括換行 '^' 匹配字符開頭,若指定flags MULTILINE,這種也能夠匹配上(r"^a","\nabc\neee",flags=re.MULTILINE) '$' 匹配字符結尾, 若指定flags MULTILINE ,re.search('foo.$','foo1\nfoo2\n',re.MULTILINE).group() 會匹配到foo1 '*' 匹配*號前的字符0次或屢次, re.search('a*','aaaabac') 結果'aaaa' '+' 匹配前一個字符1次或屢次,re.findall("ab+","ab+cd+abb+bba") 結果['ab', 'abb'] '?' 匹配前一個字符1次或0次 ,re.search('b?','alex').group() 匹配b 0次 '{m}' 匹配前一個字符m次 ,re.search('b{3}','alexbbbs').group() 匹配到'bbb' '{n,m}' 匹配前一個字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 結果'abb', 'ab', 'abb'] '|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 結果'ABC' '(...)' 分組匹配, re.search("(abc){2}a(123|45)", "abcabca456c").group() 結果爲'abcabca45' '\A' 只從字符開頭匹配,re.search("\Aabc","alexabc") 是匹配不到的,至關於re.match('abc',"alexabc") 或^ '\Z' 匹配字符結尾,同$ '\d' 匹配數字0-9 '\D' 匹配非數字 '\w' 匹配[A-Za-z0-9] '\W' 匹配非[A-Za-z0-9] 's' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 結果 '\t' '(?P<name>...)' 分組匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 結果{'province': '3714', 'city': '81', 'birthday': '1993'}
re.compile(pattern, flags=0)
Compile a regular expression pattern into a regular expression object, which can be used for matching using its match(), search() and other methods, described below.
The sequence
prog = re.compile(pattern) result = prog.match(string)
is equivalent to
result = re.match(pattern, string)
but using re.compile() and saving the resulting regular expression object for reuse is more efficient when the expression will be used several times in a single program.
re.match(pattern, string, flags=0)
從起始位置開始根據模型去字符串中匹配指定內容,匹配單個
import re obj = re.match('\d+', '123uuasf') if obj: print obj.group()
Flags標誌符
a = re.compile(r"""\d + # the integral part \. # the decimal point \d * # some fractional digits""", re.X) b = re.compile(r"\d+\.\d*")
re.search(pattern, string, flags=0)
根據模型去字符串中匹配指定內容,匹配單個
import re obj = re.search('\d+', 'u123uu888asf') if obj: print obj.group()
re.findall(pattern, string, flags=0)
match and search均用於匹配單值,即:只能匹配字符串中的一個,若是想要匹配到字符串中全部符合條件的元素,則須要使用 findall。
import re obj = re.findall('\d+', 'fa123uu888asf') print obj
re.sub(pattern, repl, string, count=0, flags=0)
用於替換匹配的字符串
>>>re.sub('[a-z]+','sb','武配齊是abc123',) >>> re.sub('\d+','|', 'alex22wupeiqi33oldboy55',count=2) 'alex|wupeiqi|oldboy55'
相比於str.replace功能更增強大
re.split(pattern, string, maxsplit=0, flags=0)
>>>s='9-2*5/3+7/3*99/4*2998+10*568/14' >>>re.split('[\*\-\/\+]',s) ['9', '2', '5', '3', '7', '3', '99', '4', '2998', '10', '568', '14'] >>> re.split('[\*\-\/\+]',s,3) ['9', '2', '5', '3+7/3*99/4*2998+10*568/14']
re.fullmatch(pattern, string, flags=0)
整個字符串匹配成功就返回re object, 不然返回None
re.fullmatch('\w+@\w+\.(com|cn|edu)',"alex@oldboyedu.cn")
1.驗證手機號是否合法
import re s = "180911827831801992342813098829384" a = re.findall("1\d{10}", s) print(a)
2.驗證郵箱是否合法
s1 = "dc0012@163.com" a1 = re.match("\w+@\w+\.(com|cn|deu)", s1) print(a1.group())
3.開發一個簡單的python計算器,實現加減乘除及拓號優先級解析
hint:
re.search(r'\([^()]+\)',s).group()#可拿到最裏層的括號中的值 '(-40/5)'