欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python實(shí)現(xiàn)基于多線程、多用戶的FTP服務(wù)器與客戶端功能完整實(shí)例

 更新時(shí)間:2017年08月18日 10:40:28   作者:水·域  
這篇文章主要介紹了Python實(shí)現(xiàn)基于多線程、多用戶的FTP服務(wù)器與客戶端功能,結(jié)合完整實(shí)例形式分析了Python多線程、多用戶FTP服務(wù)器端與客戶端相關(guān)實(shí)現(xiàn)技巧與注意事項(xiàng),需要的朋友可以參考下

本文實(shí)例講述了Python實(shí)現(xiàn)基于多線程、多用戶的FTP服務(wù)器與客戶端功能。分享給大家供大家參考,具體如下:

項(xiàng)目介紹:

1. 用戶加密認(rèn)證
2. 允許同時(shí)多用戶登錄
3. 每個(gè)用戶有自己的家目錄 ,且只能訪問(wèn)自己的家目錄
4. 對(duì)用戶進(jìn)行磁盤(pán)配額,每個(gè)用戶的可用空間不同
5. 允許用戶在ftp server上隨意切換目錄
6. 允許用戶查看當(dāng)前目錄下文件
7. 允許上傳和下載文件,保證文件一致性
8. 文件傳輸過(guò)程中顯示進(jìn)度條

實(shí)現(xiàn)的原理:

服務(wù)器端啟用端口監(jiān)聽(tīng),并對(duì)每一連接啟用一個(gè)線程,對(duì)用戶登陸密碼采用SHA512進(jìn)行加密并進(jìn)行匹配,當(dāng)用戶登陸成功后,實(shí)例化FTPS,并引導(dǎo)客戶端進(jìn)入主命令模式,

然后實(shí)現(xiàn)FTP的上傳功能、下載功能、新建目錄、刪除文件或目錄、切換目錄等實(shí)例化操作,同時(shí)對(duì)相關(guān)上傳下載進(jìn)行進(jìn)度條顯示,服務(wù)器端顯示下載或上傳文件的大小等

客戶端與服務(wù)器協(xié)商建立連接后,進(jìn)行用戶身份登陸,登陸成功接收服務(wù)器指令,轉(zhuǎn)入命令輸入窗口,同時(shí)對(duì)put 與 get命令進(jìn)行判斷,實(shí)現(xiàn)特定的上傳與下載功能

核心代碼實(shí)現(xiàn)如下:

服務(wù)器端

main.py

#!/usr/bin/env python3.5
# -*-coding:utf8-*-
import os,sys,socket,pickle
BASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASEDIR)
from conf import setting
from core import file_handler
from core import db_handler
import select,hashlib
import threading
def login(username,password):
  """
  FTP登陸驗(yàn)證函數(shù)
  :param username:
  :param password:
  :return:
  # testDict ={"username":"jjb","password":"123456","file_dir":"E:\python","file_size":500}
  # file = 'jjb.pkl'
  # fp = open(file,'wb')
  # pickle.dump(testDict,fp)
  # fp.close()
  f = open("jjb.pkl","rb")
  data = pickle.loads(f.read())
  f.close()
  print(data)
  """
  #實(shí)例化加密函數(shù)
  hash = hashlib.sha512()
  db= db_handler.handler(setting.DATABASE,username)
  if os.path.isfile(db):
    f = open(db,"rb")
    data = pickle.loads(f.read())
    f.close()
    if username == data["name"]:
      hash.update(bytes(data["password"],"utf8"))
      hash_pwd = hash.hexdigest()
      if hash_pwd == password:
        filedir = data["file_dir"]
        filesize = data["file_size"]
        return "True|%s|%s"%(filedir,filesize)
      else:
        return "False||"
    else:
      return "False||"
  else:
    return "False||"
def process(conn,addr):
  flage = "False"
  # 接收客戶端連接請(qǐng)求信息
  info = conn.recv(1000)
  if info.decode() == "connect":
    conn.send(bytes("login","utf8"))
  # 接收用戶及密碼信息
  while flage =="False":
    user_check =conn.recv(8000)
    # 分割用戶名及密碼
    username,password = str(user_check.decode()).split("|")
    # 調(diào)用登陸驗(yàn)證函數(shù)
    login_ack = login(username,password)
    flage,home,size = str(login_ack).split("|")
    # print(flage,home,size)
    # print("user_input:",username,"user_pass:",password)
    if flage =="True":
      # 登陸成功發(fā)送登陸確認(rèn)信息給客戶端
      conn.send(bytes("login_ack","utf8"))
      # 實(shí)例化FTPserver
      ftp = file_handler.FTPs(username,conn,home,size) # 登陸用戶,數(shù)據(jù)連接,工作目錄,磁盤(pán)配額
      ftp.run()
      break
    else:
      # 登陸失敗,發(fā)送給客戶端重新驗(yàn)證
      conn.send(bytes("登陸失?。?,"utf8"))
def ftp_server():
  '''
  啟動(dòng)FTP服務(wù)器端,開(kāi)啟線程監(jiān)聽(tīng)
  :return:
  '''
  server = socket.socket()
  server.bind((setting.IP_PORT["host"],setting.IP_PORT["port"]))
  server.listen(10)
  while True:
    r,w,e = select.select([server,], [], [], 1)
    for i,server in enumerate(r):
      conn,addr = server.accept()
      # 創(chuàng)建線程
      t = threading.Thread(target=process, args=(conn, addr))
      # 啟動(dòng)線程
      t.start()
  server.close()
def run():
  ftp_server()
if __name__ =="__main__":
  run()

file_handler.py:

#!/usr/bin/env python3.5
# -*-coding:utf8-*-
import os,sys
BASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASEDIR)
import re
from core import db_handler
from conf import setting
import pickle
class FTPs(object):
  '''
  ftp操作命令方法:
  '''
  def __init__(self,username,conn,home,total_size):
    '''
    初始化參數(shù)
    :param username: 操作用戶名
    :param conn: sock連接
    :param home: 用戶根目錄
    :param total_size: 磁盤(pán)配額
    :return:
    '''
    self.username = username
    self.conn = conn
    self.root = home
    self.home = self.root
    self.total_size = int(total_size)
    self.cmd_file = None # 文件指令
    self.psize = 4096 # 文件分片
  def getdirsize(self,space):
    '''
    計(jì)算磁盤(pán)空間大小
    :return:
    '''
    self.dirsize = 0
    for root,dirs,files in os.walk(space):
      self.dirsize += (sum([os.path.getsize(os.path.join(root,name))for name in files])/1024)
    return int(self.dirsize)
  def put(self):
    '''
    上傳文件
    :return:
    '''
    if self.cmd_file:
      self.user_space = int(self.getdirsize(self.root)/1024)
      # 組合接收字符串
      self.file_root = '%s\\%s'% (self.home,self.cmd_file)
      # # 獲取文件名
      self.f =os.path.basename(self.file_root)
      if os.path.isdir(self.home):
        os.chdir(self.home)
      else:
        os.makedirs(self.home)
        os.chdir(self.home)
      try:
        self.conn.send(bytes("f_ack","utf8"))
        self.size = str(self.conn.recv(1024).decode()).split("|")
        if self.size[0]== "fsize":
          self.fss = int(self.size[1])
          self.f_total_size = int(self.user_space + (self.fss/1024/1024))
          if self.f_total_size < self.total_size: # 判斷空間是否超額
            self.conn.send(bytes("f_ack_ready","utf8"))
            self.bsize = 0
            print("需要上傳文件大?。?,self.fss)
            # 打開(kāi)文件
            f=open(self.f,'wb')
            while self.bsize < self.fss:
              data = self.conn.recv(self.psize)
              self.bsize += len(data)
              f.write(data)
            self.conn.send(bytes("ok","utf8"))
            print("實(shí)際已上傳文件大?。?,self.bsize)
          else:
            self.conn.send(bytes("上傳空間不足!無(wú)法上傳,你當(dāng)前磁盤(pán)配額為%sM"%self.total_size,"utf8"))
      except Exception as ex:
        self.conn.send(bytes(ex,"utf8"))
    else:
      self.conn.send(bytes("請(qǐng)上傳文件,文件不能為空","utf8"))
  def get(self):
    '''
    下載文件
    :return:
    '''
    if self.cmd_file:
      os.chdir(self.home) # 進(jìn)入用戶根目錄
      self.file = os.getcwd()+"\\"+ self.cmd_file
      if os.path.isfile(self.file):
        f = open(self.file, 'rb')
        self.fsize = os.path.getsize(self.file) # 獲取要發(fā)送文件的大小
        self.conn.send(bytes("f_ack_read","utf8"))
        self.conn.recv(1000)
        print("需發(fā)送文件大小:",self.fsize)
        self.conn.send(bytes("fsize|%s"%self.fsize,"utf8")) # 發(fā)送文件大小及要發(fā)送準(zhǔn)備完畢指令
        if self.conn.recv(1000).decode() == "f_ack": # 接收對(duì)方是否準(zhǔn)備就緒
          self.fsize = int(self.fsize)
          self.size = 0
          ack =""
          while self.size < self.fsize and ack !="ok":
            data = f.read(self.fsize) # 一次讀取分片大小4096
            self.conn.send(data)
            self.size += len(data)
          print("實(shí)際發(fā)送文件大?。?,self.size)
          ack = self.conn.recv(1000).decode() # 接收客戶端是否下載完指令
          self.conn.send(bytes("成功","utf8"))
        else:
          self.conn.send(bytes("接收失敗","utf8"))
      else:
        self.conn.send(bytes("文件不存在","utf8"))
    else:
      self.conn.send(bytes("請(qǐng)輸入文件名","utf8"))
  def dir(self):
    '''
    查看文件
    :return:
    '''
    self.current_space =int(self.getdirsize(self.home))
    # 文件列表
    self.li = ""
    # 目錄列表
    self.dl = ""
    try:
      os.chdir(self.home)
    except:
      os.makedirs(self.home)
      os.chdir(self.home)
    try:
      if os.listdir(os.getcwd()):
        for self.i in os.listdir(os.getcwd()):
          self.file = os.getcwd()+'\\'+self.i
          if os.path.isfile(self.file):
            # 獲取文件大小
            self.fsize = int(os.path.getsize(self.file)/1024)
            if self.fsize < 1:
              self.fsize = 4
            else:
              self.fsize +=4
            self.li += '%s -rw-rw-rw- 占用大小:%skb\r\n'% (self.i,self.fsize)
          else:
            self.dl += '%s\r\n'%self.i
        self.conn.send(bytes("目錄:\r\n\r\n%s 文件:\r\n%s\r\n \r\n當(dāng)前目錄空間大?。?skb"%(self.dl,self.li,self.current_space),"utf8"))
      else:
        self.conn.send(bytes("當(dāng)前目錄為:%s"%(self.home),"utf8"))
    except Exception as ex:
      self.conn.send(bytes(ex,"utf8"))
  def cd(self):
    '''
    進(jìn)入目錄
    :return:
    '''
    if self.cmd_file:
      os.chdir(self.home) # 先進(jìn)入到工作目錄
      self.dir_change = os.path.abspath(os.path.join(self.home,"%s\%s"%(self.home,self.cmd_file)))
      if self.root in self.dir_change:
        try:
          os.chdir(self.dir_change)
          self.home = self.dir_change
          self.conn.send(bytes("當(dāng)前工作目錄為:%s"%self.home,"utf8"))
        except:
          os.makedirs(self.dir_change)
          os.chdir(self.dir_change)
          self.home = self.dir_change
          self.conn.send(bytes("當(dāng)前工作目錄為:%s"%self.home,"utf8"))
      else:
          self.conn.send(bytes("當(dāng)前工作目錄為:%s  更改失??!"%self.home,"utf8"))
    else:
      os.chdir(self.home)
      self.conn.send(bytes("當(dāng)前工作目錄為:%s"%self.home,"utf8"))
  def mkd(self):
    '''
    創(chuàng)建目錄
    :return:
    '''
    if self.cmd_file:
      try:
        os.makedirs(self.cmd_file)
        self.conn.send(bytes("創(chuàng)建目錄成功!","utf8"))
      except Exception as ex:
        self.conn.send(bytes("創(chuàng)建目錄失??!原因:%s"%ex,"utf8"))
    else:
      self.conn.send(bytes("請(qǐng)輸入文件夾名!","utf8"))
  def delete(self):
    '''
    刪除文件
    :return:
    '''
    os.chdir(self.home) # 進(jìn)入用戶根目錄
    try:
      self.file = self.home+'\\'+ self.cmd_file
      if os.path.isfile(self.file):
        os.remove(self.cmd_file)
        self.conn.send(bytes("文件:%s刪除成功!"%self.cmd_file,"utf8"))
      else:
        os.removedirs(self.cmd_file)
        self.conn.send(bytes("目錄刪除成功!","utf8"))
        os.chdir(self.root)
    except Exception:
      if os.path.isdir(self.root):
        self.conn.send(bytes("刪除失敗!","utf8"))
      else:
        os.makedirs(self.root)
        self.conn.send(bytes("刪除失??!","utf8"))
  def help(self):
    '''
    FTP幫助信息
    :return:
    '''
    self.conn.send(bytes("""
    FTP服務(wù)器操作方法有: put------>上傳文件至服務(wù)器
               get------>從服務(wù)器上下載文件
               dir------>查看服務(wù)器文件列表
               cd------->進(jìn)入指定文件夾
               delete--->刪除文件
               mkd ----->創(chuàng)建目錄
               help----->幫助信息
               q ------->退出
    ""","utf8"))
  def run(self):
    while True:
      # try:
       # # 接收客戶端發(fā)來(lái)的命令信息
      self.cmd = self.conn.recv(1000)
      self.cmd_action = str(self.cmd.decode())
      # 判斷命令是否含有空格
      self.fg = re.search("\s","%s"%self.cmd_action)
      if self.fg:
        self.cmd_action,self.cmd_file = str(self.cmd_action).split(" ")
      else:
        self.cmd_file =None
      # print("cmd_action:",self.cmd_action,"cmd_file:",self.cmd_file)
      if hasattr(FTPs,self.cmd_action):
        func = getattr(self,self.cmd_action)
        func()
        continue
      else:
        self.conn.send(b'command is not found!')
        continue
      # except Exception as ex:
      #   print("系統(tǒng)異常:%s"%ex)

客戶端

client.py:

#!/usr/bin/env python3.5
# -*-coding:utf8-*-
import sys,os,re
import socket,hashlib
BASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASEDIR)
from core import file_handler
from conf import setting
def login():
  hash = hashlib.sha512()
  while True:
    user_input = input("請(qǐng)輸入用戶名:").strip()
    pass_input = input("請(qǐng)輸入密碼:").strip()
    if len(user_input) !=0 and len(pass_input) != 0:
      hash.update(bytes(pass_input,"utf8"))
      sha_pwd = hash.hexdigest()
      user = "%s|%s"% (user_input,sha_pwd)
      return user
      break
def ftp_client():
  sk = socket.socket()
  sk.connect((setting.IP_PORT["host"],setting.IP_PORT["port"]))
  while True:
    flage = False
    sk.send(bytes("connect","utf8"))
    msg = sk.recv(100)
    print("歡迎訪問(wèn)FTP服務(wù)器,請(qǐng)根據(jù)提示進(jìn)行操作")
    if msg.decode() == "login":
      while flage == False:
        login_user =login()
        username,password = str(login_user).split("|")
        sk.send(bytes(login_user,"utf8"))
        user_info = sk.recv(1000)
        if user_info.decode() == "login_ack":
          print("登陸成功!")
          flage = True
          break
        print(user_info.decode())
      while flage:
        cmd_action = input("請(qǐng)輸入操作命令如:get fy.py or help :").strip()
        if len(cmd_action) == 0:continue
        if cmd_action == "q":
          sys.exit()
        # 判斷命令是否含有空格
        fg = re.search("\s","%s"%cmd_action)
        if fg:
          cmd,cmd_file = str(cmd_action).split(" ")
          ftp = file_handler.ftpc(sk,username,cmd_action,setting.DATABASE["local"])
          if hasattr(ftp,cmd):
            func = getattr(ftp,cmd)
            func()
            continue
        else:
          cmd_file =None
        sk.send(bytes(cmd_action,"utf8"))
        rec_msg = sk.recv(8000)
        print(rec_msg.decode())
      if flage == "False":
        sk.send(bytes("connect","utf8"))
  sk.close()
def run():
  ftp_client()
if __name__ == "__main__":
  run()

file_handler.py:

#!/usr/bin/env python3.5
# -*-coding:utf8-*-
import sys,os,re
import socket
BASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASEDIR)
class ftpc(object):
  def __init__(self,sk,username,cmd_action,home):
    self.sk = sk
    self.username = username
    self.cmd_action = cmd_action
    self.home = home
  def put(self):
    '''
    上傳文件
    :return:
    '''
    try:
      os.chdir(self.home)
    except:
      os.makedirs(self.home)
      os.chdir(self.home)
    # 判斷命令是否含有空格
    fg = re.search("\s","%s"%self.cmd_action)
    if fg:
      self.cmd,self.cmd_file = str(self.cmd_action).split(" ")
      if os.path.isfile(os.getcwd()+"\\"+self.cmd_file):
        self.sk.send(bytes(self.cmd_action,"utf8")) # 發(fā)送動(dòng)作命令
        rec_msg = self.sk.recv(8000)
        if rec_msg.decode() == "f_ack":
          f = open(self.cmd_file, 'rb')
          self.fsize = os.path.getsize(self.cmd_file) # 獲取要發(fā)送文件的大小
          self.sk.send(bytes("fsize|%s"%self.fsize,"utf8")) # 發(fā)送文件大小
          self.ack = self.sk.recv(1000)
          if self.ack.decode() =="f_ack_ready":
            self.fsize = int(self.fsize)
            self.size = 0
            ack =""
            while self.size < self.fsize and ack !="ok":
              data = f.read(4095) # 一次讀取分片大小4095
              self.sk.send(data)
              self.size += len(data)
              count = int(self.size/self.fsize*100)
              print('#'*count,"->",(count),"%")
            ack = self.sk.recv(1000).decode()
            if ack =="ok":
              print("上傳成功")
            else:
              print("上傳失敗")
          else:
            print(self.ack.decode())
        else:
          print("上傳文件失?。?s"%rec_msg.decode())
      else:
        print("上傳文件失敗,請(qǐng)輸入正確的文件名!")
    else:
      print("上傳文件失敗,請(qǐng)輸入正確的文件名!")
  def get(self):
    '''
    下載文件
    :return:
    '''
    try:
      os.chdir(self.home)
    except:
      os.makedirs(self.home)
      os.chdir(self.home)
    # 判斷命令是否含有空格
    fg = re.search("\s","%s"%self.cmd_action)
    if fg:
      self.cmd,self.cmd_file = str(self.cmd_action).split(" ")
    else:
      self.cmd_file =None
    self.sk.send(bytes(self.cmd_action,"utf8"))
    rec_msg = self.sk.recv(8000)
    if rec_msg.decode() == "f_ack_read":
      self.rec = self.sk.send(bytes("ok","utf8"))
      self.rec_size = self.sk.recv(2048)
      self.ack_rec= str(self.rec_size.decode()).split("|")
      self.sk.send(bytes("f_ack","utf8"))
      self.ack_s =int(self.ack_rec[1])
      print(self.ack_s)
      self.re_s = 0
      f = open(self.cmd_file,"wb")
      while self.re_s < self.ack_s:
        xx = self.re_s/self.ack_s*100
        data = self.sk.recv(4096)
        self.re_s += len(data)
        # print(data.decode("gbk"))
        f.write(data)
        count = int(xx)
        print('#'*count,"->",(count+1),"%")
      self.sk.send(bytes("ok","utf8"))
      print(self.re_s)
      self.ack_ok = self.sk.recv(1024)
      print("接收文件:%s"%self.ack_ok.decode())
    else:
      print("接收文件失?。?s"%rec_msg.decode())

如下是重要模塊進(jìn)行收藏:

OS模塊

os.getcwd() 獲取當(dāng)前工作目錄,即當(dāng)前python腳本工作的目錄路徑
os.chdir("dirname")  改變當(dāng)前腳本工作目錄;相當(dāng)于shell下cd
os.curdir  返回當(dāng)前目錄: ('.')
os.pardir  獲取當(dāng)前目錄的父目錄字符串名:('..')
os.makedirs('dirname1/dirname2')    可生成多層遞歸目錄
os.removedirs('dirname1')    若目錄為空,則刪除,并遞歸到上一級(jí)目錄,如若也為空,則刪除,依此類推
os.mkdir('dirname')    生成單級(jí)目錄;相當(dāng)于shell中mkdir dirname
os.rmdir('dirname')   刪除單級(jí)空目錄,若目錄不為空則無(wú)法刪除,報(bào)錯(cuò);相當(dāng)于shell中rmdir dirname
os.listdir('dirname')    列出指定目錄下的所有文件和子目錄,包括隱藏文件,并以列表方式打印
os.remove()  刪除一個(gè)文件
os.rename("oldname","newname")  重命名文件/目錄
os.stat('path/filename')  獲取文件/目錄信息
os.sep    輸出操作系統(tǒng)特定的路徑分隔符,win下為"\\",Linux下為"/"
os.linesep    輸出當(dāng)前平臺(tái)使用的行終止符,win下為"\t\n",Linux下為"\n"
os.pathsep    輸出用于分割文件路徑的字符串
os.name    輸出字符串指示當(dāng)前使用平臺(tái)。win->'nt'; Linux->'posix'
os.system("bash command")  運(yùn)行shell命令,直接顯示
os.environ  獲取系統(tǒng)環(huán)境變量
os.path.abspath(path)  返回path規(guī)范化的絕對(duì)路徑
os.path.split(path)  將path分割成目錄和文件名二元組返回
os.path.dirname(path)  返回path的目錄。其實(shí)就是os.path.split(path)的第一個(gè)元素
os.path.basename(path)  返回path最后的文件名。如何path以/或\結(jié)尾,那么就會(huì)返回空值。即os.path.split(path)的第二個(gè)元素
os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path)  如果path是絕對(duì)路徑,返回True
os.path.isfile(path)  如果path是一個(gè)存在的文件,返回True。否則返回False
os.path.isdir(path)  如果path是一個(gè)存在的目錄,則返回True。否則返回False
os.path.join(path1[, path2[, ...]])  將多個(gè)路徑組合后返回,第一個(gè)絕對(duì)路徑之前的參數(shù)將被忽略
os.path.getatime(path)  返回path所指向的文件或者目錄的最后存取時(shí)間
os.path.getmtime(path)  返回path所指向的文件或者目錄的最后修改時(shí)間

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:')
val = sys.stdin.readline()[:-1]

re 模塊

匹配格式

模式 描述
^ 匹配字符串的開(kāi)頭
$ 匹配字符串的末尾。
. 匹配任意字符,除了換行符,當(dāng)re.DOTALL標(biāo)記被指定時(shí),則可以匹配包括換行符的任意字符。
[...] 用來(lái)表示一組字符,單獨(dú)列出:[amk] 匹配 'a','m'或'k
[^...] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re* 匹配0個(gè)或多個(gè)的表達(dá)式。
re+ 匹配1個(gè)或多個(gè)的表達(dá)式。
re? 匹配0個(gè)或1個(gè)由前面的正則表達(dá)式定義的片段,非貪婪方式
re{ n}
re{ n,} 精確匹配n個(gè)前面表達(dá)式。
re{ n, m} 匹配 n 到 m 次由前面的正則表達(dá)式定義的片段,貪婪方式
a| b 匹配a或b
(re) G匹配括號(hào)內(nèi)的表達(dá)式,也表示一個(gè)組
(?imx) 正則表達(dá)式包含三種可選標(biāo)志:i, m, 或 x 。只影響括號(hào)中的區(qū)域。
(?-imx) 正則表達(dá)式關(guān)閉 i, m, 或 x 可選標(biāo)志。只影響括號(hào)中的區(qū)域。
(?: re) 類似 (...), 但是不表示一個(gè)組
(?imx: re) 在括號(hào)中使用i, m, 或 x 可選標(biāo)志
(?-imx: re) 在括號(hào)中不使用i, m, 或 x 可選標(biāo)志
(?#...) 注釋.
(?= re) 前向肯定界定符。如果所含正則表達(dá)式,以 ... 表示,在當(dāng)前位置成功匹配時(shí)成功,否則失敗。但一旦所含表達(dá)式已經(jīng)嘗試,匹配引擎根本沒(méi)有提高;模式的剩余部分還要嘗試界定符的右邊。
(?! re) 前向否定界定符。與肯定界定符相反;當(dāng)所含表達(dá)式不能在字符串當(dāng)前位置匹配時(shí)成功
(?> re) 匹配的獨(dú)立模式,省去回溯。
\w 匹配字母數(shù)字
\W 匹配非字母數(shù)字
\s 匹配任意空白字符,等價(jià)于 [\t\n\r\f].
\S 匹配任意非空字符
\d 匹配任意數(shù)字,等價(jià)于 [0-9].
\D 匹配任意非數(shù)字
\A 匹配字符串開(kāi)始
\Z 匹配字符串結(jié)束,如果是存在換行,只匹配到換行前的結(jié)束字符串。c
\z 匹配字符串結(jié)束
\G 匹配最后匹配完成的位置。
\b 匹配一個(gè)單詞邊界,也就是指單詞和空格間的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 匹配非單詞邊界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\n, \t, 等. 匹配一個(gè)換行符。匹配一個(gè)制表符。等
\1...\9 匹配第n個(gè)分組的子表達(dá)式。
\10 匹配第n個(gè)分組的子表達(dá)式,如果它經(jīng)匹配。否則指的是八進(jìn)制字符碼的表達(dá)式。

正則表達(dá)式常用5種操作

re.match(pattern, string) # 從頭匹配
re.search(pattern, string) # 匹配整個(gè)字符串,直到找到一個(gè)匹配
re.split() # 將匹配到的格式當(dāng)做分割點(diǎn)對(duì)字符串分割成列表

>>>m = re.split("[0-9]", "alex1rain2jack3helen rachel8")
>>>print(m)

輸出:['alex', 'rain', 'jack', 'helen rachel', '']

re.findall() # 找到所有要匹配的字符并返回列表格式

>>>m = re.findall("[0-9]", "alex1rain2jack3helen rachel8")
>>>print(m)

輸出:['1', '2', '3', '8']

re.sub(pattern, repl, string, count,flag) # 替換匹配到的字符

m=re.sub("[0-9]","|", "alex1rain2jack3helen rachel8",count=2 )
print(m)

輸出:alex|rain|jack3helen rachel8

正則表達(dá)式實(shí)例

字符匹配

實(shí)例 描述
python 匹配 "python".

字符類

實(shí)例 描述
[Pp]ython 匹配 "Python" 或 "python
rub[ye] 匹配 "ruby" 或 "rube
[aeiou] 匹配中括號(hào)內(nèi)的任意一個(gè)字母
[0-9] 匹配任何數(shù)字。類似于 [0123456789]
[a-z] 匹配任何小寫(xiě)字母
[A-Z] 匹配任何大寫(xiě)字母
[a-zA-Z0-9] 匹配任何字母及數(shù)字
[^aeiou] 除了aeiou字母以外的所有字符
[^0-9] 匹配除了數(shù)字外的字符

特殊字符類

實(shí)例 描述
. 匹配除 "\n" 之外的任何單個(gè)字符。要匹配包括 '\n' 在內(nèi)的任何字符,請(qǐng)使用象 '[.\n]' 的模式。
\d 匹配一個(gè)數(shù)字字符。等價(jià)于 [0-9]。
\D 匹配一個(gè)非數(shù)字字符。等價(jià)于 [^0-9]。
\s 匹配任何空白字符,包括空格、制表符、換頁(yè)符等等。等價(jià)于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等價(jià)于 [^ \f\n\r\t\v]。
\w 匹配包括下劃線的任何單詞字符。等價(jià)于'[A-Za-z0-9_]'。
\W 匹配任何非單詞字符。等價(jià)于 '[^A-Za-z0-9_]'。

re.match與re.search的區(qū)別

re.match只匹配字符串的開(kāi)始,如果字符串開(kāi)始不符合正則表達(dá)式,則匹配失敗,函數(shù)返回None;而re.search匹配整個(gè)字符串,直到找到一個(gè)匹配。

PS:這里再為大家提供2款非常方便的正則表達(dá)式工具供大家參考使用:

JavaScript正則表達(dá)式在線測(cè)試工具:
http://tools.jb51.net/regex/javascript

正則表達(dá)式在線生成工具:
http://tools.jb51.net/regex/create_reg

更多關(guān)于Python相關(guān)內(nèi)容可查看本站專題:《Python正則表達(dá)式用法總結(jié)》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》、《Python入門(mén)與進(jìn)階經(jīng)典教程》及《Python文件與目錄操作技巧匯總

希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • Python中查找缺失值的三種方法

    Python中查找缺失值的三種方法

    本文主要介紹了Python中查找缺失值的三種方法,包括pandas庫(kù)的isnull()方法、numpy庫(kù)的isnan()方法和scikit-learn庫(kù)的SimpleImputer類,感興趣的可以了解一下
    2023-11-11
  • python入門(mén)語(yǔ)句基礎(chǔ)之if語(yǔ)句、while語(yǔ)句

    python入門(mén)語(yǔ)句基礎(chǔ)之if語(yǔ)句、while語(yǔ)句

    本文介紹了python入門(mén)語(yǔ)句基礎(chǔ)之if語(yǔ)句、while語(yǔ)句,if?語(yǔ)句讓你能夠檢查程序的當(dāng)前狀態(tài),并據(jù)此采取相應(yīng)的措施,而for?循環(huán)用于針對(duì)集合中的每個(gè)元素都一個(gè)代碼塊,而?while?循環(huán)不斷地運(yùn)行,直到指定的條件不滿足為止,本文通過(guò)示例代碼詳解介紹,需要的朋友參考下吧
    2022-04-04
  • django與小程序?qū)崿F(xiàn)登錄驗(yàn)證功能的示例代碼

    django與小程序?qū)崿F(xiàn)登錄驗(yàn)證功能的示例代碼

    這篇文章主要介紹了django與小程序?qū)崿F(xiàn)登錄驗(yàn)證功能的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • OpenCV基于ORB算法實(shí)現(xiàn)角點(diǎn)檢測(cè)

    OpenCV基于ORB算法實(shí)現(xiàn)角點(diǎn)檢測(cè)

    這篇文章主要為大家詳細(xì)介紹了OpenCV基于ORB算法實(shí)現(xiàn)角點(diǎn)檢測(cè),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • Python實(shí)現(xiàn)自定義讀寫(xiě)分離代碼實(shí)例

    Python實(shí)現(xiàn)自定義讀寫(xiě)分離代碼實(shí)例

    這篇文章主要介紹了Python實(shí)現(xiàn)自定義讀寫(xiě)分離代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Python多線程編程(四):使用Lock互斥鎖

    Python多線程編程(四):使用Lock互斥鎖

    這篇文章主要介紹了Python多線程編程(四):使用Lock互斥鎖,本文講解了互斥鎖概念、同步阻塞、代碼示例等內(nèi)容,需要的朋友可以參考下
    2015-04-04
  • python實(shí)現(xiàn)按關(guān)鍵字篩選日志文件

    python實(shí)現(xiàn)按關(guān)鍵字篩選日志文件

    今天小編大家分享一篇python實(shí)現(xiàn)按關(guān)鍵字篩選日志文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-12-12
  • Python ckeditor富文本編輯器代碼實(shí)例解析

    Python ckeditor富文本編輯器代碼實(shí)例解析

    這篇文章主要介紹了Python ckeditor富文本編輯器代碼實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Python?局部變量global詳解

    Python?局部變量global詳解

    這篇文章主要介紹了Python?局部變量global詳解,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • Python實(shí)現(xiàn)基本Socket服務(wù)端與客戶端通信的完整代碼

    Python實(shí)現(xiàn)基本Socket服務(wù)端與客戶端通信的完整代碼

    這篇文章主要介紹了Python實(shí)現(xiàn)基本Socket服務(wù)端與客戶端通信,分步詳解與完整代碼都有,按需所求即可,對(duì)Python Socket服務(wù)端與客戶端通信相關(guān)知識(shí)感興趣的朋友一起看看吧
    2023-06-06

最新評(píng)論