天天看點

python 學習筆記8 (子產品)

Python 子產品(Module),是一個 Python 檔案,以 .py 結尾,包含了 Python 對象定義和Python語句。

子產品讓你能夠有邏輯地組織你的 Python 代碼段。

把相關的代碼配置設定到一個子產品裡能讓你的代碼更好用,更易懂。

子產品能定義函數,類和變量,子產品裡也能包含可執行的代碼。

通俗的講:

  子產品,用一堆代碼實作了某個功能的代碼集合。 

  類似于函數式程式設計和面向過程程式設計,函數式程式設計則完成一個功能,其他代碼用來調用即可,提供了代碼的重用性和代碼間的耦合。而對于一個複雜的功能來,可能需要多個函數才能完成(函數又可以在不同的.py檔案中),n個 .py 檔案組成的代碼集合就稱為子產品。

如:os 是系統相關的子產品;file是檔案操作相關的子產品

子產品分為三種:

  • 自定義子產品
  • 内置子產品
  • 開源子產品

自定義子產品

1、定義子產品

情景一:

  

情景二:

  

情景三:

  

2、導入子產品

Python之是以應用越來越廣泛,在一定程度上也依賴于其為程式員提供了大量的子產品以供使用,如果想要使用子產品,則需要導入。導入子產品有一下幾種方法:

import module
from module.xx.xx import xx
from module.xx.xx import xx as rename  
from module.xx.xx import *      

導入子產品其實就是告訴Python解釋器去解釋那個py檔案

  • 導入一個py檔案,解釋器解釋該py檔案
  • 導入一個包,解釋器解釋該包下的 __init__.py 檔案

那麼問題來了,導入子產品時是根據那個路徑作為基準來進行的呢?即:sys.path

import sys
print(sys.path)

['C:\Users\Administrator\PycharmProjects\suanfa', 'C:\Users\Administrator\PycharmProjects\suanfa', 'E:\python\python3\python35.zip', 'E:\python\python3\DLLs', 'E:\python\python3\lib', 'E:\python\python3', 'C:\Users\Administrator\AppData\Roaming\Python\Python35\site-packages', 'E:\python\python3\lib\site-packages', 'E:\python\python3\lib\site-packages\win32', 'E:\python\python3\lib\site-packages\win32\lib', 'E:\python\python3\lib\site-packages\Pythonwin']      

如果sys.path路徑清單沒有你想要的路徑,可以通過 sys.path.append('路徑') 添加。

通過os子產品可以擷取各種目錄,例如:

import sys
import os

pre_path = os.path.abspath('../')
sys.path.append(pre_path)      

View Code

開源子產品

一、下載下傳安裝

下載下傳安裝有兩種方式:

1.
yum 
pip
apt-get      
2.
下載下傳源碼
解壓源碼
進入目錄
編譯源碼    python setup.py build
安裝源碼    python setup.py install      

在使用源碼安裝時,需要使用到gcc編譯和python開發環境,是以,需要先執行:

yum install gcc
yum install python-devel
或
apt-get python-dev      

安裝成功後,子產品會自動安裝到 sys.path 中的某個目錄中,如:

/usr/lib/python2.7/site-packages/      

二、導入子產品

同自定義子產品中導入的方式

三、子產品 paramiko

paramiko是一個用于做遠端控制的子產品,使用該子產品可以對遠端伺服器進行指令或檔案操作,值得一說的是,fabric和ansible内部的遠端管理就是使用的paramiko來現實。

1、下載下傳安裝

pip3 install paramiko

或

# pycrypto,由于 paramiko 子產品内部依賴pycrypto,是以先下載下傳安裝pycrypto
 
# 下載下傳安裝 pycrypto
wget http://files.cnblogs.com/files/wupeiqi/pycrypto-2.6.1.tar.gz
tar -xvf pycrypto-2.6.1.tar.gz
cd pycrypto-2.6.1
python setup.py build
python setup.py install
 
# 進入python環境,導入Crypto檢查是否安裝成功
 
# 下載下傳安裝 paramiko
wget http://files.cnblogs.com/files/wupeiqi/paramiko-1.10.1.tar.gz
tar -xvf paramiko-1.10.1.tar.gz
cd paramiko-1.10.1
python setup.py build
python setup.py install
 
# 進入python環境,導入paramiko檢查是否安裝成功      

View Code

2、使用子產品

import paramiko

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.14.50', 22, 'liu', '123')
stdin, stdout, stderr = ssh.exec_command('df')
print stdout.read()
ssh.close();      

執行指令 - 通過使用者名和密碼連接配接伺服器

import paramiko

private_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(private_key_path)

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('主機名 ', 端口, '使用者名', key)

stdin, stdout, stderr = ssh.exec_command('ls')
print stdout.read()
ssh.close()      

執行指令 - 過密鑰連結伺服器

import os,sys
import paramiko

t = paramiko.Transport(('192.168.14.50',22))
t.connect(username='liu',password='123')
sftp = paramiko.SFTPClient.from_transport(t)
sftp.put('/tmp/test.py','/tmp/test.py') 
t.close()


import os,sys
import paramiko

t = paramiko.Transport(('192.168.14.50',22))
t.connect(username='liu',password='123')
sftp = paramiko.SFTPClient.from_transport(t)
sftp.get('/tmp/test.py','/tmp/test2.py')
t.close()      

上傳或者下載下傳檔案 - 通過使用者名和密碼

import paramiko

pravie_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(pravie_key_path)

t = paramiko.Transport(('192.168.14.51',22))
t.connect(username='liu',pkey=key)

sftp = paramiko.SFTPClient.from_transport(t)
sftp.put('/tmp/test3.py','/tmp/test3.py') 

t.close()

import paramiko

pravie_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(pravie_key_path)

t = paramiko.Transport(('192.168.14.51',22))
t.connect(username='liu',pkey=key)


sftp = paramiko.SFTPClient.from_transport(t)
sftp.get('/tmp/test3.py','/tmp/test4.py') 

t.close()      

上傳或下載下傳檔案 - 通過密鑰

内置子產品

一、os

用于提供系統級别的操作

os.getcwd() 擷取目前工作目錄,即目前python腳本工作的目錄路徑
os.chdir("dirname")  改變目前腳本工作目錄;相當于shell下cd
os.curdir  傳回目前目錄: ('.')
os.pardir  擷取目前目錄的父目錄字元串名:('..')
os.makedirs('dirname1/dirname2')    可生成多層遞歸目錄
os.removedirs('dirname1')    若目錄為空,則删除,并遞歸到上一級目錄,如若也為空,則删除,依此類推
os.mkdir('dirname')    生成單級目錄;相當于shell中mkdir dirname
os.rmdir('dirname')    删除單級空目錄,若目錄不為空則無法删除,報錯;相當于shell中rmdir dirname
os.listdir('dirname')    列出指定目錄下的所有檔案和子目錄,包括隐藏檔案,并以清單方式列印
os.remove()  删除一個檔案
os.rename("oldname","newname")  重命名檔案/目錄
os.stat('path/filename')  擷取檔案/目錄資訊
os.sep    輸出作業系統特定的路徑分隔符,win下為"\",Linux下為"/"
os.linesep    輸出目前平台使用的行終止符,win下為"	
",Linux下為"
"
os.pathsep    輸出用于分割檔案路徑的字元串
os.name    輸出字元串訓示目前使用平台。win->'nt'; Linux->'posix'
os.system("bash command")  運作shell指令,直接顯示
os.environ  擷取系統環境變量
os.path.abspath(path)  傳回path規範化的絕對路徑
os.path.split(path)  将path分割成目錄和檔案名二進制組傳回
os.path.dirname(path)  傳回path的目錄。其實就是os.path.split(path)的第一個元素
os.path.basename(path)  傳回path最後的檔案名。如何path以/或結尾,那麼就會傳回空值。即os.path.split(path)的第二個元素
os.path.exists(path)  如果path存在,傳回True;如果path不存在,傳回False
os.path.isabs(path)  如果path是絕對路徑,傳回True
os.path.isfile(path)  如果path是一個存在的檔案,傳回True。否則傳回False
os.path.isdir(path)  如果path是一個存在的目錄,則傳回True。否則傳回False
os.path.join(path1[, path2[, ...]])  将多個路徑組合後傳回,第一個絕對路徑之前的參數将被忽略
os.path.getatime(path)  傳回path所指向的檔案或者目錄的最後存取時間
os.path.getmtime(path)  傳回path所指向的檔案或者目錄的最後修改時間      

View Code

二、sys

用于提供對解釋器相關的操作

sys.argv           指令行參數List,第一個元素是程式本身路徑
sys.exit(n)        退出程式,正常退出時exit(0)
sys.version        擷取Python解釋程式的版本資訊
sys.maxint         最大的Int值
sys.path           傳回子產品的搜尋路徑,初始化時使用PYTHONPATH環境變量的值
sys.platform       傳回作業系統平台名稱
sys.stdout.write('please:')
val = sys.stdin.readline()[:-1]      

View Code

三、hashlib 

用于加密相關的操作,代替了md5子產品和sha子產品,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

廢棄的md5
import md5
hash = md5.new()
hash.update('admin')
print hash.hexdigest()

廢棄的sha
import sha

hash = sha.new()
hash.update('admin')
print hash.hexdigest()

新寫法

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

以上加密算法雖然依然非常厲害,但時候存在缺陷,即:通過撞庫可以反解。是以,有必要對加密算法中添加自定義key再來做加密。

import hashlib
 
# ######## md5 ########
 
hash = hashlib.md5('898oaFs09f')
hash.update('admin')
print hash.hexdigest()

python 還有一個 hmac 子產品,它内部對我們建立 key 和 内容 再進行處理然後再加密

import hmac
h = hmac.new('wueiqi')
h.update('hellowo')
print h.hexdigest()      

View Code

四、json 和 pickle 

JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。它基于ECMAScript的一個子集。 JSON采用完全獨立于語言的文本格式,但是也使用了類似于C語言家族的習慣(包括C、C++、Java、JavaScript、Perl、Python等)。這些特性使JSON成為理想的資料交換語言。易于人閱讀和編寫,同時也易于機器解析和生成(一般用于提升網絡傳輸速率)。

JSON在python中分别由list和dict組成。

pickle子產品實作了python的所有資料序列和反序列化。基本上功能使用和JSON子產品沒有太大差別,方法也同樣是dumps/dump和loads/load。

與JSON不同的是pickle不是用于多種語言間的資料傳輸,它僅作為python對象的持久化或者python程式間進行互相傳輸對象的方法,是以它支援了python所有的資料類型。

pickle反序列化後的對象與原對象是等值的副本對象,類似與deepcopy。

簡易來講就是這兩個子產品是用于序列化的

  • json,用于字元串 和 python資料類型間進行轉換
  • pickle,用于python特有的類型 和 python的資料類型間進行轉換

Json子產品提供了四個功能:dumps、dump、loads、load

pickle子產品提供了四個功能:dumps、dump、loads、load

import json
dic = {"name":"liu"}
data = json.dumps(dic)
f = open("Json_test","w")
f.write(data)
f.close()

import json
f = open("Json_test","r")
json.load(f)
f.close()      
import pickle
def foo():
    print("ok")
f = open("Pickle_test","wb")
data = pickle.dump(foo,f)
f.close()

import pickle
def foo():
    print("ok")
f = open("Pickle_test","rb")
pickle.load(f)
f.close()      
dumps:  将對象序列化

import json

# 簡單編碼===========================================
print json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
# ["foo", {"bar": ["baz", null, 1.0, 2]}]

#字典排序
print json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
# {"a": 0, "b": 0, "c": 0}

#自定義分隔符
print json.dumps([1,2,3,{'4': 5, '6': 7}], sort_keys=True, separators=(',',':'))
# [1,2,3,{"4":5,"6":7}]
print json.dumps([1,2,3,{'4': 5, '6': 7}], sort_keys=True, separators=('/','-'))
# [1/2/3/{"4"-5/"6"-7}]

#增加縮進,增強可讀性,但縮進空格會使資料變大
print json.dumps({'4': 5, '6': 7}, sort_keys=True,indent=2, separators=(',', ': '))
# {
#   "4": 5,
#   "6": 7
# }

# 另一個比較有用的dumps參數是skipkeys,預設為False。
# dumps方法存儲dict對象時,key必須是str類型,如果出現了其他類型的話,那麼會産生TypeError異常,如果開啟該參數,設為True的話,會忽略這個key。
data = {'a':1,(1,2):123}
print json.dumps(data,skipkeys=True)
#{"a": 1}

dump:  将對象序列化并儲存到檔案

#将對象序列化并儲存到檔案
obj = ['foo', {'bar': ('baz', None, 1.0, 2)}]
with open(r"c:json.txt","w+") as f:
    json.dump(obj,f)

loads:  将序列化字元串反序列化

import json

obj = ['foo', {'bar': ('baz', None, 1.0, 2)}]
a= json.dumps(obj)
print json.loads(a)
# [u'foo', {u'bar': [u'baz', None, 1.0, 2]}]

 load:  将序列化字元串從檔案讀取并反序列化

with open(r"c:json.txt","r") as f:
    print json.load(f)      

json四個功能

自定義複雜資料類型編解碼

例如我們碰到對象datetime,或者自定義的類對象等json預設不支援的資料類型時,我們就需要自定義編解碼函數。有兩種方法來實作自定義編解碼。

方法一:自定義編解碼函數

import datetime,json

dt = datetime.datetime.now()



def time2str(obj):
    #python to json
    if isinstance(obj, datetime.datetime):
        json_str = {"datetime":obj.strftime("%Y-%m-%d %X")}
        return json_str
    return obj

def str2time(json_obj):
    #json to python
    if "datetime" in json_obj:
        date_str,time_str = json_obj["datetime"].split(' ')
        date = [int(x) for x in date_str.split('-')]
        time = [int(x) for x in time_str.split(':')]
        dt = datetime.datetime(date[0],date[1], date[2], time[0],time[1], time[2])
        return dt
    return json_obj


a = json.dumps(dt,default=time2str)
print a
# {"datetime": "2016-10-27 17:38:31"}
print json.loads(a,object_hook=str2time)
# 2016-9-2 17:38:31      

View Code

方法二:繼承JSONEncoder和JSONDecoder類,重寫相關方法

import datetime,json

dt = datetime.datetime.now()
dd = [dt,[1,2,3]]

class MyEncoder(json.JSONEncoder):
    def default(self,obj):
        #python to json
        if isinstance(obj, datetime.datetime):
            json_str = {"datetime":obj.strftime("%Y-%m-%d %X")}
            return json_str
        return obj

class MyDecoder(json.JSONDecoder):
    def __init__(self):
        json.JSONDecoder.__init__(self, object_hook=self.str2time)

    def str2time(self,json_obj):
        #json to python
        if "datetime" in json_obj:
            date_str,time_str = json_obj["datetime"].split(' ')
            date = [int(x) for x in date_str.split('-')]
            time = [int(x) for x in time_str.split(':')]
            dt = datetime.datetime(date[0],date[1], date[2], time[0],time[1], time[2])
            return dt
        return json_obj


# a = json.dumps(dt,default=time2str)
a =MyEncoder().encode(dd)
print a
# [{"datetime": "2016-10-27 18:14:54"}, [1, 2, 3]]
print MyDecoder().decode(a)
# [datetime.datetime(2016, 9, 27, 18, 14, 54), [1, 2, 3]]      

View Code

dumps/dump序列化

from datetime import date

try:
    import cPickle as pickle    #python 2
except ImportError as e:
    import pickle   #python 3


src_dic = {"date":date.today(),"oth":([1,"a"],None,True,False),}
det_str = pickle.dumps(src_dic)
print det_str
# (dp1
# S'date'
# p2
# cdatetime
# date
# p3
# (S'x07xe0
x1b'
# tRp4
# sS'oth'
# p5
# ((lp6
# I1
# aS'a'
# aNI01
# I00
# tp7
# s.
with open(r"c:pickle.txt","w") as f:
    pickle.dump(src_dic,f)

loads/load反序列化

from datetime import date

try:
    import cPickle as pickle    #python 2
except ImportError as e:
    import pickle   #python 3


src_dic = {"date":date.today(),"oth":([1,"a"],None,True,False),}
det_str = pickle.dumps(src_dic)
with open(r"c:pickle.txt","r") as f:
    print pickle.load(f)
# {'date': datetime.date(2016, 9, 27), 'oth': ([1, 'a'], None, True, False)}      

pickle 功能

JSON和pickle子產品的差別

1、JSON隻能處理基本資料類型。pickle能處理所有Python的資料類型。

2、JSON用于各種語言之間的字元轉換。pickle用于Python程式對象的持久化或者Python程式間對象網絡傳輸,但不同版本的Python序列化可能還有差異。

五、執行系統指令 

可以執行shell指令的相關子產品和函數有:

  • os.system
  • os.spawn*
  • os.popen*          --廢棄
  • popen2.*           --廢棄
  • commands.*      --廢棄,3.x中被移除
import commands

result = commands.getoutput('cmd')
result = commands.getstatus('cmd')
result = commands.getstatusoutput('cmd')      

commands

以上執行shell指令的相關的子產品和函數的功能均在 subprocess 子產品中實作,并提供了更豐富的功能。

call 

執行指令,傳回狀态碼

ret = subprocess.call(["ls", "-l"], shell=False)
ret = subprocess.call("ls -l", shell=True)      

shell = True ,允許 shell 指令是字元串形式

check_call

執行指令,如果執行狀态碼是 0 ,則傳回0,否則抛異常

subprocess.check_call(["ls", "-l"])
subprocess.check_call("exit 1", shell=True)      

check_output

執行指令,如果狀态碼是 0 ,則傳回執行結果,否則抛異常

subprocess.check_output(["echo", "Hello World!"])
subprocess.check_output("exit 1", shell=True)      

subprocess.Popen(...)

用于執行複雜的系統指令

參數:

  • args:shell指令,可以是字元串或者序列類型(如:list,元組)
  • bufsize:指定緩沖。0 無緩沖,1 行緩沖,其他 緩沖區大小,負值 系統緩沖
  • stdin, stdout, stderr:分别表示程式的标準輸入、輸出、錯誤句柄
  • preexec_fn:隻在Unix平台下有效,用于指定一個可執行對象(callable object),它将在子程序運作之前被調用
  • close_sfs:在windows平台下,如果close_fds被設定為True,則新建立的子程序将不會繼承父程序的輸入、輸出、錯誤管道。

    是以不能将close_fds設定為True同時重定向子程序的标準輸入、輸出與錯誤(stdin, stdout, stderr)。

  • shell:同上
  • cwd:用于設定子程序的目前目錄
  • env:用于指定子程序的環境變量。如果env = None,子程序的環境變量将從父程序中繼承。
  • universal_newlines:不同系統的換行符不同,True -> 同意使用
  • startupinfo與createionflags隻在windows下有效

    将被傳遞給底層的CreateProcess()函數,用于設定子程序的一些屬性,如:主視窗的外觀,程序的優先級等等

import subprocess
ret1 = subprocess.Popen(["mkdir","t1"])
ret2 = subprocess.Popen("mkdir t2", shell=True)      

執行普通指令

終端輸入的指令分為兩種:

  • 輸入即可得到輸出,如:ifconfig
  • 輸入進行某環境,依賴再輸入,如:python
import subprocess

obj = subprocess.Popen("mkdir t3", shell=True, cwd='/home/dev',)      

View Code

import subprocess

obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
obj.stdin.write('print 1 
 ')
obj.stdin.write('print 2 
 ')
obj.stdin.write('print 3 
 ')
obj.stdin.write('print 4 
 ')
obj.stdin.close()

cmd_out = obj.stdout.read()
obj.stdout.close()
cmd_error = obj.stderr.read()
obj.stderr.close()

print (cmd_out)
print (cmd_error)      

View Code

import subprocess

obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
obj.stdin.write('print 1 
 ')
obj.stdin.write('print 2 
 ')
obj.stdin.write('print 3 
 ')
obj.stdin.write('print 4 
 ')

out_error_list = obj.communicate()
print (out_error_list)      

View Code

import subprocess

obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out_error_list = obj.communicate('print "hello"')
print(out_error_list)      

View Code

六、logging

用于便捷記錄日志且線程安全的子產品

組成

主要分為四個部分:

  • Loggers:提供應用程式直接使用的接口
  • Handlers:将Loggers産生的日志傳到指定位置
  • Filters:對輸出日志進行過濾
  • Formatters:控制輸出格式
import logging
 
 
logging.basicConfig(filename='log.log',
                    format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S %p',
                    level=10)
 
logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')
logging.log(10,'log')      

等級:

CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0      

隻有大于目前日志等級的操作才會被記錄。

七、time

時間相關的操作,時間有三種表示方式:

  • 時間戳               1970年1月1日之後的秒,即:time.time()
  • 格式化的字元串    2014-11-11 11:11,    即:time.strftime('%Y-%m-%d')
  • 結構化時間          元組包含了:年、日、星期等... time.struct_time    即:time.localtime()
print time.time()
print time.mktime(time.localtime())
  
print time.gmtime()    #可加時間戳參數
print time.localtime() #可加時間戳參數
print time.strptime('2014-11-11', '%Y-%m-%d')
  
print time.strftime('%Y-%m-%d') #預設目前時間
print time.strftime('%Y-%m-%d',time.localtime()) #預設目前時間
print time.asctime()
print time.asctime(time.localtime())
print time.ctime(time.time())
  
import datetime
'''
datetime.date:表示日期的類。常用的屬性有year, month, day
datetime.time:表示時間的類。常用的屬性有hour, minute, second, microsecond
datetime.datetime:表示日期時間
datetime.timedelta:表示時間間隔,即兩個時間點之間的長度
timedelta([days[, seconds[, microseconds[, milliseconds[, minutes[, hours[, weeks]]]]]]])
strftime("%Y-%m-%d")
'''
import datetime
print datetime.datetime.now()
print datetime.datetime.now() - datetime.timedelta(days=5)      

View Code

八、re 

re子產品用于對python的正規表達式的操作。

字元:

  . 比對除換行符以外的任意字元

  w 比對字母或數字或下劃線或漢字

  s 比對任意的空白符

  d 比對數字

   比對單詞的開始或結束

  ^ 比對字元串的開始

  $ 比對字元串的結束

次數:

  * 重複零次或更多次

  + 重複一次或更多次

  ? 重複零次或一次

  {n} 重複n次

  {n,} 重複n次或更多次

  {n,m} 重複n到m次

1、match(pattern, string, flags=0)

從起始位置開始根據模型去字元串中比對指定内容,比對單個

  • 正規表達式
  • 要比對的字元串
  • 标志位,用于控制正規表達式的比對方式
import re

obj = re.match('d+', '123uuasf')
if obj:
    print(obj.group())      

2、search(pattern, string, flags=0)

根據模型去字元串中比對指定内容,比對單個

import re

obj = re.search('d+', 'u123uu888asf')
if obj:
    print (obj.group())      

3、group和groups

import re
a = "123abc456"
print (re.search("([0-9]*)([a-z]*)([0-9]*)", a).group())

print (re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(0))
print (re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(1))
print (re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(2))

print (re.search("([0-9]*)([a-z]*)([0-9]*)", a).groups())

結果
123abc456
123abc456
123
abc
('123', 'abc', '456')      

4、findall(pattern, string, flags=0)

上述兩中方式均用于比對單值,即:隻能比對字元串中的一個,如果想要比對到字元串中所有符合條件的元素,則需要使用 findall。

import re
obj = re.findall('d+', 'fa123uu888asf')
print (obj)

結果
['123', '888']      

5、sub(pattern, repl, string, count=0, flags=0)

用于替換比對的字元串

content = "123abc456"
new_content = re.sub('d+', 'sb', content)
# new_content = re.sub('d+', 'sb', content, 1)
print (new_content)

結果
sbabcsb      

相比于str.replace功能更加強大

6、split(pattern, string, maxsplit=0, flags=0)

根據指定比對進行分組

content = "'1 - 2 * ((60-30+1*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2) )'"
new_content = re.split('[+-*/]+', content)
# new_content = re.split('*', content, 1)
print (new_content)

結果:
["'1 ", ' 2 ', ' ((60', '30', '1', '(9', '2', '5', '3', '7', '3', '99', '4', '2998', '10', '568', '14))', '(', '4', '3)', '(16', '3', "2) )'"]      
inpp = '1-2*((60-30 +(-40-5)*(9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))'
inpp = re.sub('s*','',inpp)
new_content = re.split('(([+-*/]?d+[+-*/]?d+){1})', inpp, 1)
print (new_content)

結果:
['1-2*((60-30+', '-40-5', '*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']      
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
該電腦思路:
    1、遞歸尋找表達式中隻含有 數字和運算符的表達式,并計算結果
    2、由于整數計算會忽略小數,所有的數字都認為是浮點型操作,以此來保留小數
使用技術:
    1、正規表達式
    2、遞歸
 
執行流程如下:
******************** 請計算表達式: 1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) ********************
before: ['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
-40.0/5=-8.0
after: ['1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
========== 上一次計算結束 ==========
before: ['1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
9-2*5/3+7/3*99/4*2998+10*568/14=173545.880953
after: ['1-2*((60-30+-8.0*173545.880953)-(-4*3)/(16-3*2))']
========== 上一次計算結束 ==========
before: ['1-2*((60-30+-8.0*173545.880953)-(-4*3)/(16-3*2))']
60-30+-8.0*173545.880953=-1388337.04762
after: ['1-2*(-1388337.04762-(-4*3)/(16-3*2))']
========== 上一次計算結束 ==========
before: ['1-2*(-1388337.04762-(-4*3)/(16-3*2))']
-4*3=-12.0
after: ['1-2*(-1388337.04762--12.0/(16-3*2))']
========== 上一次計算結束 ==========
before: ['1-2*(-1388337.04762--12.0/(16-3*2))']
16-3*2=10.0
after: ['1-2*(-1388337.04762--12.0/10.0)']
========== 上一次計算結束 ==========
before: ['1-2*(-1388337.04762--12.0/10.0)']
-1388337.04762--12.0/10.0=-1388335.84762
after: ['1-2*-1388335.84762']
========== 上一次計算結束 ==========
我的計算結果: 2776672.69524
"""
 
 
import re
 
 
def compute_mul_div(arg):
    """ 操作乘除
    :param expression:表達式
    :return:計算結果
    """
 
    val = arg[0]
    mch = re.search('d+.*d*[*/]+[+-]?d+.*d*', val)
    if not mch:
        return
    content = re.search('d+.*d*[*/]+[+-]?d+.*d*', val).group()
 
    if len(content.split('*'))>1:
        n1, n2 = content.split('*')
        value = float(n1) * float(n2)
    else:
        n1, n2 = content.split('/')
        value = float(n1) / float(n2)
 
    before, after = re.split('d+.*d*[*/]+[+-]?d+.*d*', val, 1)
    new_str = "%s%s%s" % (before,value,after)
    arg[0] = new_str
    compute_mul_div(arg)
 
 
def compute_add_sub(arg):
    """ 操作加減
    :param expression:表達式
    :return:計算結果
    """
    while True:
        if arg[0].__contains__('+-') or arg[0].__contains__("++") or arg[0].__contains__('-+') or arg[0].__contains__("--"):
            arg[0] = arg[0].replace('+-','-')
            arg[0] = arg[0].replace('++','+')
            arg[0] = arg[0].replace('-+','-')
            arg[0] = arg[0].replace('--','+')
        else:
            break
 
    if arg[0].startswith('-'):
        arg[1] += 1
        arg[0] = arg[0].replace('-','&')
        arg[0] = arg[0].replace('+','-')
        arg[0] = arg[0].replace('&','+')
        arg[0] = arg[0][1:]
    val = arg[0]
    mch = re.search('d+.*d*[+-]{1}d+.*d*', val)
    if not mch:
        return
    content = re.search('d+.*d*[+-]{1}d+.*d*', val).group()
    if len(content.split('+'))>1:
        n1, n2 = content.split('+')
        value = float(n1) + float(n2)
    else:
        n1, n2 = content.split('-')
        value = float(n1) - float(n2)
 
    before, after = re.split('d+.*d*[+-]{1}d+.*d*', val, 1)
    new_str = "%s%s%s" % (before,value,after)
    arg[0] = new_str
    compute_add_sub(arg)
 
 
def compute(expression):
    """ 操作加減乘除
    :param expression:表達式
    :return:計算結果
    """
    inp = [expression,0]
 
    # 處理表達式中的乘除
    compute_mul_div(inp)
 
    # 處理
    compute_add_sub(inp)
    if divmod(inp[1],2)[1] == 1:
        result = float(inp[0])
        result = result * -1
    else:
        result = float(inp[0])
    return result
 
 
def exec_bracket(expression):
    """ 遞歸處理括号,并計算
    :param expression: 表達式
    :return:最終計算結果
    """
    # 如果表達式中已經沒有括号,則直接調用負責計算的函數,将表達式結果傳回,如:2*1-82+444
    if not re.search('(([+-*/]*d+.*d*){2,})', expression):
        final = compute(expression)
        return final
    # 擷取 第一個 隻含有 數字/小數 和 操作符 的括号
    # 如:
    #    ['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
    #    找出:(-40.0/5)
    content = re.search('(([+-*/]*d+.*d*){2,})', expression).group()
 
    # 分割表達式,即:
    # 将['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
    # 分割更三部分:['1-2*((60-30+(    (-40.0/5)      *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
    before, nothing, after = re.split('(([+-*/]*d+.*d*){2,})', expression, 1)
 
    print 'before:',expression
    content = content[1:len(content)-1]
 
    # 計算,提取的表示 (-40.0/5),并活的結果,即:-40.0/5=-8.0
    ret = compute(content)
 
    print '%s=%s' %( content, ret)
 
    # 将執行結果拼接,['1-2*((60-30+(      -8.0     *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
    expression = "%s%s%s" %(before, ret, after)
    print 'after:',expression
    print "="*10,'上一次計算結束',"="*10
 
    # 循環繼續下次括号處理操作,本次攜帶者的是已被處理後的表達式,即:
    # ['1-2*((60-30+   -8.0  *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
 
    # 如此周而複始的操作,直到表達式中不再含有括号
    return exec_bracket(expression)
 
 
 
# 使用 __name__ 的目的:
#   隻有執行 python index.py 時,以下代碼才執行
#   如果其他人導入該子產品,以下代碼不執行
if __name__ == "__main__":
    #print '*'*20,"請計算表達式:", "1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )" ,'*'*20
    #inpp = '1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) '
    inpp = "1-2*-30/-12*(-20+200*-3/-200*-300-100)"
    #inpp = "1-5*980.0"
    inpp = re.sub('s*','',inpp)
    # 表達式儲存在清單中
    result = exec_bracket(inpp)
    print result      

大王版電腦

#__author__:Administrator
#__date__:2016/9/13
import re
def mi(arg):
    while True:
        relust = re.split("(d+.?d*-?[*]{2}-?d+.?d*)", arg, 1)
        if len(relust) == 3:
            x = relust[0]
            y = relust[1]
            z = relust[2]
            if "**" in y:
                start,end = y.split("**")
                finlly = float(start) ** float(end)
                arg = x + str(finlly) + z
        else:
            return arg
def chengchu(arg):
    while True:                                                                 #while循環每一次傳進來的運算
        arg = arg.replace("++","+")
        arg = arg.replace("+-","-")
        arg = arg.replace("-+","-")
        arg = arg.replace("--","+")
        arg = arg.replace("*+","*")
        arg = arg.replace("/+","/")
        relust = re.split("(d+.?d*-?[*/]-?d+.?d*)",arg,1)              #把從左往右第一次比對到得乘法
        if len(relust) ==3:
            x = relust[0]
            y = relust[1]
            z = relust[2]
            if "*" in y :
                start,end = y.split("*")                                 #用“*”把分割開指派給start,end
                finlly = float(start) * float(end)                             #運算出乘法
                arg = x+str(finlly)+z                                #替換原來的運算式
            else:
                start, end = y.split("/")                                #用/分割開指派給start,end
                finlly = float(start) / float(end)
                arg = x + str(finlly) + z                             #替換原來的元算式
        else:
            return arg                                                         #将運算結果傳回去
def jiajian(arg):
    result = re.findall("[+-]?d+.?d*",arg)                            #列出所有的元素
    start = 0                                                                  #定義空值依次去加
    for i in result:
        start += float(i)                                       #所有元素相加
    return start                                                     #傳回運算結果
def jisuan(source):
    while True:
        source = source.replace(" ", "")                                       #去掉空格
        res = re.split("(([^()]*))",source,1)                                   #先取出括号裡面的值
        if len(res) ==3:
            x = res[0]                                                          #分别将元素指派給三個值
            y = res[1]
            z = res[2]
            powe = mi(y)
            ch = chengchu(powe)                                        #執行乘除
            jj = jiajian(ch)                                                 #執行加減
            res = x + str(jj) + z                                      #運算結果替換原來等式
            source = res                                                            #指派給其他傳進來元素
        else:                                                              #沒括号得等式
            powe = mi(source)
            ch = chengchu(powe)                                             #計算乘法法
            jj = jiajian(ch)                                                 #計算加法
            source = jj
            return source
while True:
    choice = input("請輸入計算等式(q退出):")
    if choice =="q":
        print("再見!")
        break
    elif choice == "":
        print("-----請輸入算式-----")
        continue
    elif re.findall("[a-zA-Z@#¥%&]", choice):
        print("--輸入不規範,請輸入算式!--")
        continue
    else:
        value = jisuan(choice)
        print("計算結果為:%s" % value)
        print("eval結果為:%s" % eval(choice))      

自己版電腦

九、random

随機數

import random
print (random.random())
print (random.randint(1,2))
print (random.randrange(1,10))      
import random
checkcode = ''
for i in range(4):
    current = random.randrange(0,4)
    if current != i:
        temp = chr(random.randint(65,90))
    else:
        temp = random.randint(0,9)
    checkcode += str(temp)
print (checkcode)      

随機驗證碼執行個體