精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Python 如何僅用 5000 行代碼,實現(xiàn)強(qiáng)大的 logging 模塊?

開發(fā) 前端
Python 的 logging 模塊實現(xiàn)了靈活的日志系統(tǒng)。整個模塊僅僅 3 個類,不到 5000 行代碼的樣子,學(xué)習(xí)它可以加深對程序日志的了解

 

Python 的 logging 模塊實現(xiàn)了靈活的日志系統(tǒng)。整個模塊僅僅 3 個類,不到 5000 行代碼的樣子,學(xué)習(xí)它可以加深對程序日志的了解,本文分下面幾個部分:

  • logging 簡介

  • logging API 設(shè)計

  • 記錄器對象 Logger

  • 日志記錄對象 LogRecord

  • 處理器對象 Hander

  • 格式器對象 Formatter

  • 滾動日志文件處理器

  • 小結(jié)

  • 小技巧

logging 簡介

本次代碼使用的是 python 3.8.5 的版本,官方中文文檔 3.8.8 。參考鏈接中官方中文文檔非常詳細(xì),建議先看一遍了解日志使用。

功能
logging-module logging的API
Logger 日志記錄器對象類,可以創(chuàng)建一個對象用來記錄日志
LogRecord 日志記錄對象,每條日志記錄都封裝成一個日志記錄對象
Hander 處理器對象,負(fù)責(zé)日志輸出到流/文件的控制
Formatter 格式器,負(fù)責(zé)日志記錄的格式化
RotatingFileHandler 按大小滾動的日志文件記錄器
TimedRotatingFileHandler 按時間滾動的日志文件處理器

我們主要研究日志如何輸出到標(biāo)準(zhǔn)窗口這一主線;日志的配置,日志的線程安全及各種特別的Handler等支線可以先忽略。

logging API 設(shè)計

先看看日志使用:

  1. import logging 
  2.  
  3. logging.basicConfig(level=logging.INFO, format='%(levelname)-8s %(name)-10s %(asctime)s %(message)s'
  4. lang = {"name""python""age":20
  5. logging.info('This is a info message %s', lang) 
  6. logging.debug('This is a debug message'
  7. logging.warning('This is a warning message'
  8.  
  9. logger = logging.getLogger(__name__) 
  10. logger.warning('This is a warning'

輸出內(nèi)容如下:

  1. INFO     root       2021-03-04 00:03:53,473 This is a info message {'name''python''age'20
  2. WARNING  root       2021-03-04 00:03:53,473 This is a warning message 
  3. WARNING  __main__   2021-03-04 00:03:53,473 This is a warning 

可以看到 logging 的使用非常方便,模塊直接提供了一組API。

  1. root = RootLogger(WARNING)  # 默認(rèn)提供的logger 
  2. Logger.root = root 
  3. Logger.manager = Manager(Logger.root) 
  4.  
  5. def debug(msg, *args, **kwargs): # info,warning等api類似 
  6.     if len(root.handlers) == 0
  7.         basicConfig()  # 默認(rèn)配置 
  8.     root.debug(msg, *args, **kwargs) 
  9.  
  10. def getLogger(name=None): 
  11.     if name: 
  12.         return Logger.manager.getLogger(name)  # 創(chuàng)建特定的logger 
  13.     else
  14.         return root  # 返回默認(rèn)的logger 

這種API的提供方式,我們在 requests 中也有看到。api中很重要的設(shè)置config的方式:

  1. def basicConfig(**kwargs): 
  2.     ... 
  3.     if handlers is None: 
  4.         filename = kwargs.pop("filename", None) 
  5.         mode = kwargs.pop("filemode"'a'
  6.         if filename: 
  7.             h = FileHandler(filename, mode) 
  8.         else
  9.             stream = kwargs.pop("stream", None) 
  10.             h = StreamHandler(stream)  # 默認(rèn)的handler 
  11.         handlers = [h] 
  12.     dfs = kwargs.pop("datefmt", None) 
  13.     style = kwargs.pop("style"'%'
  14.     fs = kwargs.pop("format", _STYLES[style][1]) 
  15.     fmt = Formatter(fs, dfs, style)  # 生成formatter 
  16.     for h in handlers: 
  17.         if h.formatter is None: 
  18.             h.setFormatter(fmt) 
  19.         root.addHandler(h)  # 設(shè)置root的handler 
  20.     level = kwargs.pop("level", None) 
  21.     if level is not None: 
  22.         root.setLevel(level)  # 設(shè)置日志級別 

可以看到,日志的配置主要包括下面幾項:

  • level 日志級別

  • format 信息格式化模版

  • filename 輸出到文件

  • datefmt %Y-%m-%d %H:%M:%S,uuu 時間的格式模版
  • style [ % , { ,$] 格式樣板

演示代碼輸出中,可以看到debug日志沒有顯示,是因為 debug < info :

  1. CRITICAL = 50 
  2. FATAL = CRITICAL 
  3. ERROR = 40 
  4. WARNING = 30 
  5. WARN = WARNING 
  6. INFO = 20 
  7. DEBUG = 10 
  8. NOTSET = 0 

記錄器對象 Logger

查看Logger之前,先看logger對象的管理類Manager

  1. _loggerClass = Logger 
  2.  
  3. class Manager(object): 
  4.     def __init__(self, rootnode): 
  5.         self.root = rootnode 
  6.         self.disable = 0 
  7.         self.loggerDict = {}  # 所有日志記錄對象的字典 
  8.     ... 
  9.     def getLogger(self, name): 
  10.         rv = None 
  11.         if name in self.loggerDict: 
  12.             rv = self.loggerDict[name]  # 獲取已經(jīng)創(chuàng)建過的同名logger 
  13.             ... 
  14.         else
  15.             rv = (self.loggerClass or _loggerClass)(name)  # 創(chuàng)建新的logger 
  16.             rv.manager = self 
  17.             self.loggerDict[name] = rv 
  18.             ... 
  19.         return rv 

日志過濾器

  1. class Filterer(object): 
  2.  
  3.     def __init__(self): 
  4.         self.filters = [] 
  5.  
  6.     def addFilter(self, filter): 
  7.         self.filters.append(filter) 
  8.  
  9.     def removeFilter(self, filter): 
  10.         self.filters.remove(filter) 
  11.  
  12.     def filter(self, record): 
  13.         rv = True 
  14.         for f in self.filters:  # 過濾日志 
  15.             if hasattr(f, 'filter'): 
  16.                 result = f.filter(record) 
  17.             else
  18.                 result = f(record) # assume callable - will raise if not 
  19.             if not result: 
  20.                 rv = False 
  21.                 break 
  22.         return r 

核心的 Logger 實際上只是一個控制中心:

  1. class Logger(Filterer):  # logger可以過濾日志 
  2.     def __init__(self, name, level=NOTSET): 
  3.         Filterer.__init__(self) 
  4.         self.name = name 
  5.         self.level = _checkLevel(level) 
  6.         self.parent = None  # 日志可以有層級 
  7.         self.propagate = True 
  8.         self.handlers = []  # 可以輸出到多個handler 
  9.         self.disabled = False  # 可以關(guān)閉 
  10.         self._cache = {} 
  11.      
  12.     def debug(self, msg, *args, **kwargs):  # 輸出debug日志 
  13.         if self.isEnabledFor(DEBUG): 
  14.             self._log(DEBUG, msg, args, **kwargs) 

logger可以判斷日志級別:

  1. def isEnabledFor(self, level): 
  2.     if self.disabled: 
  3.         return False 
  4.  
  5.     try
  6.         return self._cache[level] 
  7.     except KeyError: 
  8.         try
  9.             if self.manager.disable >= level: 
  10.                 is_enabled = self._cache[level] = False 
  11.             else
  12.                 is_enabled = self._cache[level] = ( 
  13.                     level >= self.getEffectiveLevel() 
  14.                 ) 
  15.         return is_enabled 
  16.  
  17. def getEffectiveLevel(self): 
  18.     logger = self 
  19.     while logger: 
  20.         if logger.level: 
  21.             return logger.level 
  22.         logger = logger.parent 
  23.     return NOTSET 

日志輸出:

  1. def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False, 
  2.          stacklevel=1): 
  3.     ... 
  4.     fn, lno, func = "(unknown file)"0"(unknown function)" 
  5.     ... 
  6.     # 生成日志記錄 
  7.     record = self.makeRecord(self.name, level, fn, lno, msg, args, 
  8.                              exc_info, func, extra, sinfo) 
  9.     # 使用handler處理日志 
  10.     self.handle(record) 

日志記錄的生產(chǎn),就是創(chuàng)建一個LogRecord對象:

  1. _logRecordFactory = LogRecord 
  2.  
  3. def makeRecord(self, name, level, fn, lno, msg, args, exc_info, 
  4.                func=None, extra=None, sinfo=None): 
  5.     ... 
  6.     rv = _logRecordFactory(name, level, fn, lno, msg, args, exc_info, func, 
  7.                          sinfo) 
  8.     ... 
  9.     return rv 

使用logger對象的所有handler處理日志:

  1. def handle(self, record): 
  2.     c = self 
  3.     found = 0 
  4.     while c: 
  5.         for hdlr in c.handlers:  # 使用所有的handler處理日志 
  6.             found = found + 1 
  7.             if record.levelno >= hdlr.level: 
  8.                 hdlr.handle(record) 

root-logger的handler是在config中配置的:

  1. def basicConfig(**kwargs): 
  2.     ... 
  3.     root.addHandler(h)  # 設(shè)置root的handler 

日志記錄對象 LogRecord

日志記錄對象非常簡單:

  1. class LogRecord(object): 
  2.     def __init__(self, name, level, pathname, lineno, 
  3.                  msg, args, exc_info, func=None, sinfo=None, **kwargs): 
  4.         ct = time.time() 
  5.         self.name = name  # logger名稱 
  6.         self.msg = msg  # 日志標(biāo)識信息 
  7.         ... 
  8.         self.args = args  # 變量 
  9.         self.levelname = getLevelName(level) 
  10.         ... 
  11.      
  12.     def getMessage(self): 
  13.         msg = str(self.msg) 
  14.         if self.args: 
  15.             msg = msg % self.args  # 格式化消息 
  16.         return msg 

處理器對象 Hander

頂級Handler定義了Handler的模版方法

  1. class Handler(Filterer):  # 處理器也可以過濾日志 
  2.     def __init__(self, level=NOTSET): 
  3.         Filterer.__init__(self) 
  4.         self._name = None 
  5.         self.level = _checkLevel(level)  # handler也有日志級別 
  6.         self.formatter = None 
  7.         _addHandlerRef(self) 
  8.         self.createLock() 
  9.          
  10.     def handle(self, record):  # 處理日志 
  11.         rv = self.filter(record)  # 過濾日志 
  12.         if rv: 
  13.             self.acquire()  # 申請鎖 
  14.             try
  15.                 self.emit(record)  # 提交記錄,由不同子類實現(xiàn)  
  16.             finally
  17.                 self.release()  # 釋放鎖 
  18.         return rv 

默認(rèn)的console流 StreamHandler

  1. class StreamHandler(Handler): 
  2.  
  3.     terminator = '\n'  # 自動換行 
  4.  
  5.     def __init__(self, stream=None): 
  6.         Handler.__init__(self) 
  7.         if stream is None: 
  8.             stream = sys.stderr  # 默認(rèn)使用stderr輸出 
  9.         self.stream = stream 
  10.      
  11.     def emit(self, record): 
  12.         try
  13.             msg = self.format(record)  # 格式化日志記錄 
  14.             stream = self.stream 
  15.             stream.write(msg + self.terminator)  # 寫日志 
  16.             self.flush()  # 刷新寫緩存 
  17.         except Exception: 
  18.             ... 
  19.      
  20.     def format(self, record): 
  21.         if self.formatter: 
  22.             fmt = self.formatter 
  23.         else
  24.             fmt = _defaultFormatter 
  25.         return fmt.format(record)  # 使用格式化器格式化日志記錄 

為什么使用stderr,可以看下面的測試中的輸出都是到console:

  1. print("haha"
  2. print("fatal error", file=sys.stderr) 
  3. sys.stderr.write("fatal error\n"

格式器對象 Formatter

格式化器主要使用Formatter和Style實現(xiàn)

  1. class Formatter(object): 
  2.     def __init__(self, fmt=None, datefmt=None, style='%', validate=True): 
  3.         self._style = _STYLES[style][0](fmt) 
  4.         self._fmt = self._style._fmt 
  5.         self.datefmt = datefmt 
  6.      
  7.     def format(self, record): 
  8.         record.message = record.getMessage() 
  9.         s = self.formatMessage(record) 
  10.         return s 
  11.          
  12.     def formatMessage(self, record): 
  13.         return self._style.format(record)  # 格式化 

Style類

  1. class PercentStyle(object): 
  2.  
  3.     default_format = '%(message)s' 
  4.     asctime_format = '%(asctime)s' 
  5.     asctime_search = '%(asctime)' 
  6.     validation_pattern = re.compile(r'%\(\w+\)[#0+ -]*(\*|\d+)?(\.(\*|\d+))?[diouxefgcrsa%]', re.I) 
  7.  
  8.     def __init__(self, fmt): 
  9.         self._fmt = fmt or self.default_format 
  10.  
  11.     def usesTime(self): 
  12.         return self._fmt.find(self.asctime_search) >= 0 
  13.  
  14.     def validate(self): 
  15.         """Validate the input format, ensure it matches the correct style""" 
  16.         if not self.validation_pattern.search(self._fmt): 
  17.             raise ValueError("Invalid format '%s' for '%s' style" % (self._fmt, self.default_format[0])) 
  18.  
  19.     def _format(self, record): 
  20.         return self._fmt % record.__dict__  # 格式化日志記錄對象 
  21.  
  22.     def format(self, record): 
  23.         try
  24.             return self._format(record) 
  25.         except KeyError as e: 
  26.             raise ValueError('Formatting field not found in record: %s' % e) 

滾動日志文件處理器

線上的日志持續(xù)輸出到一個文件的話,會讓文件巨大,即有加劇了丟失的風(fēng)險,也難以處理。通常有按照大小滾動或者按照日期滾動的方法,這個功能非常重要。先看滾動日志處理器模版:

  1. class BaseRotatingHandler(logging.FileHandler): 
  2.     def emit(self, record): 
  3.         try
  4.             if self.shouldRollover(record): # 判斷是否需要滾動 
  5.                 self.doRollover()  # 滾動日志 
  6.             logging.FileHandler.emit(self, record)  # 輸出日志 
  7.         except Exception: 
  8.             self.handleError(record) 
  9.      
  10.     def rotate(self, source, dest): 
  11.         if not callable(self.rotator): 
  12.             if os.path.exists(source): 
  13.                 os.rename(source, dest)  # 重命名日志文件 
  14.         else
  15.             self.rotator(source, dest) 

按大小滾動 RotatingFileHandler

按照文件大小滾動的處理器:

  1. class RotatingFileHandler(BaseRotatingHandler): 
  2.  
  3.     def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False): 
  4.         if maxBytes > 0
  5.             mode = 'a' 
  6.         BaseRotatingHandler.__init__(self, filename, mode, encoding, delay) 
  7.         self.maxBytes = maxBytes  # 單個文件大小上限 
  8.         self.backupCount = backupCount  # 日志備份數(shù)量 
  9.          
  10.     def doRollover(self):  # 執(zhí)行滾動 
  11.         if self.stream: 
  12.             self.stream.close()  # 關(guān)閉當(dāng)前的流 
  13.             self.stream = None 
  14.         if self.backupCount > 0
  15.             for i in range(self.backupCount - 10, -1): 
  16.                 sfn = self.rotation_filename("%s.%d" % (self.baseFilename, i)) 
  17.                 dfn = self.rotation_filename("%s.%d" % (self.baseFilename, 
  18.                                                         i + 1)) 
  19.                 if os.path.exists(sfn): 
  20.                     if os.path.exists(dfn): 
  21.                         os.remove(dfn) 
  22.                     os.rename(sfn, dfn) 
  23.             dfn = self.rotation_filename(self.baseFilename + ".1"
  24.             if os.path.exists(dfn): 
  25.                 os.remove(dfn) 
  26.             self.rotate(self.baseFilename, dfn)  # 重命名文件 
  27.         if not self.delay: 
  28.             self.stream = self._open()  # 如果shouldRollover延遲,可以打開新的流 
  29.  
  30.     def shouldRollover(self, record):  # 判斷是否需要滾動 
  31.         if self.stream is None:  # 立即打開流 
  32.             self.stream = self._open() 
  33.         if self.maxBytes > 0:    
  34.             msg = "%s\n" % self.format(record) 
  35.             self.stream.seek(02)  #due to non-posix-compliant Windows feature 
  36.             if self.stream.tell() + len(msg) >= self.maxBytes:  # 判斷大小 
  37.                 return 1 
  38.         return 0 

文件大小滾動就是在記錄日志時候判斷文檔是否超過上限,超過則重命名舊日志,生成新日志。

按照日期滾動 TimedRotatingFileHandler

按照日期滾動的處理器:

  1. class TimedRotatingFileHandler(BaseRotatingHandler): 
  2.     def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None): 
  3.         BaseRotatingHandler.__init__(self, filename, 'a', encoding, delay) 
  4.         self.when = when.upper() 
  5.         self.backupCount = backupCount 
  6.         self.utc = utc 
  7.         self.atTime = atTime 
  8.         # 日期設(shè)置,支持多種方式 
  9.         if self.when == 'S'
  10.             self.interval = 1 # one second 
  11.             self.suffix = "%Y-%m-%d_%H-%M-%S" 
  12.             self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}(\.\w+)?$" 
  13.         ... 
  14.  
  15.         self.extMatch = re.compile(self.extMatch, re.ASCII) 
  16.         self.interval = self.interval * interval # multiply by units requested 
  17.         filename = self.baseFilename 
  18.         if os.path.exists(filename): 
  19.             t = os.stat(filename)[ST_MTIME]  # 最后修改時間 
  20.         else
  21.             t = int(time.time()) 
  22.         self.rolloverAt = self.computeRollover(t)  # 提前計算終止時間 
  23.  
  24.     def computeRollover(self, currentTime): 
  25.         # 判斷的方法還是很長很復(fù)雜的,先pass 
  26.  
  27.     def shouldRollover(self, record): 
  28.         t = int(time.time()) 
  29.         if t >= self.rolloverAt:  # 判斷是否到期 
  30.             return 1 
  31.         return 0 
  32.  
  33.     def doRollover(self): 
  34.         ... 
  35.         dfn = self.rotation_filename(self.baseFilename + "." + 
  36.                                      time.strftime(self.suffix, timeTuple)) 
  37.         #  滾動日志文件 
  38.         if os.path.exists(dfn): 
  39.             os.remove(dfn) 
  40.         self.rotate(self.baseFilename, dfn) 
  41.         if self.backupCount > 0
  42.             for s in self.getFilesToDelete(): 
  43.                 os.remove(s) 
  44.         ... 
  45.         # 計算下一個時間點 
  46.         newRolloverAt = self.computeRollover(currentTime) 
  47.         ... 
  48.         self.rolloverAt = newRolloverAt 

日期滾動就是計算最后時間點,超過時間點則重新生成新的日志文件。

小結(jié)

logging的處理邏輯大概是這樣的:

  • 創(chuàng)建Logger對象,提供API,用來接收應(yīng)用程序日志

  • Logger對象包括多個Handler

  • 每個Handler有一個Formatter對象

  • 每條日志都會生成一個LogRecord對象

  • 使用不同的Handler對象將LogRecored對象提交到不同的流

  • 每個日志對象通過Formatter格式化輸出

  • 可以使用按日期/文件大小的方式進(jìn)行日志文件的滾動記錄

小技巧

覆蓋對象的 __reduce__ 方法,讓對象支持 reduce 函數(shù):

  1. class RootLogger(Logger): 
  2.     def __init__(self, level): 
  3.         Logger.__init__(self, "root", level) 
  4.  
  5.     def __reduce__(self): 
  6.         return getLogger, () 

線程鎖的創(chuàng)建和釋放:

  1. _lock = threading.RLock() 
  2.  
  3. def _acquireLock(): 
  4.     if _lock: 
  5.         _lock.acquire() 
  6.  
  7. def _releaseLock(): 
  8.     if _lock: 
  9.         _lock.release() 

線程鎖的使用:

  1. def addHandler(self, hdlr): 
  2.     _acquireLock() 
  3.     try
  4.         self.handlers.append(hdlr) 
  5.     finally
  6.         _releaseLock() 
  7.  
  8. def removeHandler(self, hdlr): 
  9.     _acquireLock() 
  10.     try
  11.         self.handlers.remove(hdlr) 
  12.     finally
  13.         _releaseLock() 

參考鏈接

  • Logging in Python https://realpython.com/python-logging/

  • 日志操作手冊 https://docs.python.org/zh-cn/3.8/howto/logging-cookbook.html#cookbook-rotator-namer

  • Python 的日志記錄工具 https://docs.python.org/zh-cn/3.8/library/logging.html

 

 

責(zé)任編輯:張燕妮 來源: 游戲不存在
相關(guān)推薦

2021-10-13 08:16:14

SQL 代碼系統(tǒng)

2015-02-09 10:43:00

JavaScript

2021-10-18 11:05:51

SQL源代碼AddUpdate

2022-05-11 09:02:27

Python數(shù)據(jù)庫Excel

2020-09-28 12:34:38

Python代碼開發(fā)

2021-09-09 05:57:57

JS模塊打包器前端

2025-06-10 08:10:59

Cursor代碼AI

2022-03-04 09:59:16

logging模塊函數(shù)程序

2020-09-24 11:10:05

Python代碼字符串

2020-06-11 08:48:49

JavaScript開發(fā)技術(shù)

2018-01-23 09:17:22

Python人臉識別

2022-03-26 22:28:06

加密通信Python

2022-04-09 09:11:33

Python

2015-09-29 10:26:51

pythonlogging模塊

2025-04-01 08:20:00

Logging模塊Python日志記錄

2014-10-09 09:46:01

Apache模塊

2020-04-10 12:25:28

Python爬蟲代碼

2020-08-19 10:30:25

代碼Python多線程

2015-08-10 11:09:09

Python代碼Python

2019-09-25 09:20:41

谷歌代碼開發(fā)者
點贊
收藏

51CTO技術(shù)棧公眾號

国产免费黄色片| 亚洲熟妇一区二区三区| 不卡一本毛片| 久久久五月婷婷| 91精品在线看| 啦啦啦免费高清视频在线观看| 精品美女久久久| 91精品免费在线| 人人干视频在线| 97在线观看免费观看高清| 国产美女精品人人做人人爽| 69久久夜色精品国产7777 | 国产成人精品片| 日韩在线看片| 日韩精品视频在线| 亚洲成人福利视频| 欧美大片1688网站| 亚洲成人一二三| 亚洲欧洲精品一区二区| 日本高清视频在线| 狠狠色狠狠色综合| 日本一区二区在线播放| 久久久精品视频在线| 国产剧情在线观看一区| 亚洲第一精品福利| 亚洲综合伊人久久| 中韩乱幕日产无线码一区| 午夜免费久久看| 老汉色影院首页| av黄色在线观看| 久久这里只有精品首页| 成人av播放| 国产乱子伦精品无码码专区| 天堂资源在线中文精品| 97国产精品视频人人做人人爱| 久艹在线观看视频| 日韩精品一区二区久久| 精品亚洲男同gayvideo网站| 国产ts在线观看| 麻豆国产精品| 91精品国产91久久综合桃花| 尤蜜粉嫩av国产一区二区三区| 欧美a级在线观看| 亚洲五月六月丁香激情| 男人添女人下部视频免费| 成人影院在线观看| 国产精品九色蝌蚪自拍| 午夜一区二区三区| 国产对白叫床清晰在线播放| 91麻豆国产福利精品| 好吊色欧美一区二区三区| 9i看片成人免费看片| 中文精品久久| 欧美成人精品激情在线观看| 91香蕉视频在线播放| 国产精品99一区二区三区| 日韩在线观看免费高清| 三级在线观看免费大全| 亚洲天天综合| 欧美另类第一页| 久久一二三四区| 亚洲国产mv| 欧美在线视频观看免费网站| 久久99国产综合精品免费| 老鸭窝毛片一区二区三区| 国产成一区二区| 综合网在线观看| 日韩精品成人一区二区三区| 国产精品久久久久久网站| 在线免费a视频| 久久99精品久久久久婷婷| 成人国产精品一区二区| 亚洲av色香蕉一区二区三区| youjizz国产精品| 美女精品国产| 香蕉视频在线看| 一区二区三区中文在线| 九色自拍视频在线观看| 蜜桃精品在线| 在线综合亚洲欧美在线视频| 无码人妻一区二区三区免费n鬼沢| 国产日韩三级| 亚洲人成电影网站色| 国产精品69久久久久孕妇欧美| 亚洲国产一区二区在线观看| 久久久爽爽爽美女图片| 一级一片免费看| 国产麻豆精品在线| 精品免费一区二区三区蜜桃| 1区2区3区在线观看| 一区二区三区自拍| 欧美成人精品欧美一级乱| 五月天色综合| 亚洲精品久久久久国产| 黑人と日本人の交わりビデオ| 你懂的国产精品永久在线| 国产91精品久久久| 国产精品欧美久久久久天天影视 | 欧美视频完全免费看| 欧美日韩精品区别| 欧美一区二区三区久久| 久久精品免费电影| 五月婷婷激情视频| 国产精品一区二区久久不卡| 欧美一级日本a级v片| 伊人春色在线观看| 欧美这里有精品| 午夜视频在线观看国产| 97精品国产| 奇米四色中文综合久久| 国产成人精品一区二区无码呦 | 一个人www视频在线免费观看| 欧美日韩一区二区三区高清 | 国产肥臀一区二区福利视频| 亚洲男人在线| 亚洲欧美日本另类| 国产第100页| 狠狠久久亚洲欧美| 无码免费一区二区三区免费播放 | 色呦呦一区二区三区| 五月天国产视频| 日韩欧美一区二区三区在线视频| 2020久久国产精品| 亚洲第一视频在线| 国产精品国产三级国产三级人妇| 成年网站在线免费观看| 91九色鹿精品国产综合久久香蕉| 综合136福利视频在线| 久久久久99精品成人片我成大片| 成人免费av资源| 无码人妻aⅴ一区二区三区日本| 电影久久久久久| 日韩精品在线免费观看| 国产91av视频| 成人黄色在线看| 蜜臀精品一区二区| 日韩视频一二区| 久久亚洲影音av资源网| 91麻豆成人精品国产| 国产欧美日韩精品a在线观看| 欧洲黄色一级视频| 丝袜美腿综合| 97成人超碰免| 天堂v视频永久在线播放| 亚洲一区欧美一区| 99免费观看视频| 狠狠色丁香久久综合频道| 91九色极品视频| 尤物视频在线看| 欧美成人精品福利| 国产在线欧美在线| proumb性欧美在线观看| 国产乱子伦农村叉叉叉| 亚洲警察之高压线| 日产日韩在线亚洲欧美| 搞黄视频在线观看| 欧美日韩国产影片| 欧美大片xxxx| 懂色av中文字幕一区二区三区 | 日韩av不卡一区二区| 日韩精品无码一区二区三区| 懂色aⅴ精品一区二区三区| 色哟哟网站入口亚洲精品| 一区二区视频在线免费观看| 亚洲特级片在线| 国产精九九网站漫画| 99精品国产在热久久| 麻豆精品传媒视频| 日韩一区二区三区免费视频| 色偷偷av一区二区三区乱| aaa级黄色片| 性感美女久久精品| 欧美特黄一区二区三区| 黄色日韩网站视频| 欧美国产视频一区| 欧美欧美黄在线二区| 国产美女高潮久久白浆| 污污在线观看| 日韩精品免费在线视频| 精品国产青草久久久久96| 中文字幕日韩一区二区| 国产精品久久久久久久无码| 日韩精品视频网站| 黄色小视频大全| 小说区图片区色综合区| 国产欧美精品在线| 超碰在线97国产| 国产午夜精品一区二区三区 | 亚洲精品理论电影| 中文字幕+乱码+中文乱码www| 亚洲视频一区二区在线观看| 精品人妻伦一二三区久| 美美哒免费高清在线观看视频一区二区| 欧美日韩一级在线| 亚洲国产欧美日韩在线观看第一区| 国产精品视频99| 2021中文字幕在线| 色香阁99久久精品久久久| 色婷婷av一区二区三| 777亚洲妇女| 69国产精品视频免费观看| 亚洲男人电影天堂| 国产成人精品无码免费看夜聊软件| 精品亚洲成av人在线观看| 精品99在线视频| 在线中文一区| 日韩一区不卡| 亚洲经典视频| 成人国产精品色哟哟| 97se综合| 国模私拍视频一区| 国产激情在线视频| 伊人伊成久久人综合网站| 涩涩视频免费看| 91精品视频网| 艳妇乳肉豪妇荡乳av无码福利| 亚洲1区2区3区视频| 久久嫩草捆绑紧缚| 国产视频一区二区在线| 老熟妇精品一区二区三区| 国产一区二区精品久久| 污污网站免费看| 亚洲免费婷婷| 久久视频这里有精品| 亚洲色图欧美| 中文字幕欧美人与畜| av中字幕久久| 日韩在线观看电影完整版高清免费| 久久99国产精品久久99大师| 999热视频| 麻豆精品在线| 91色视频在线导航| 图片一区二区| 成人春色激情网| 四虎影视精品永久在线观看| 国产精品第10页| 欧美二三四区| 日本欧美在线视频| 女生影院久久| 日本精品在线视频| 亚洲黄色免费av| 欧美亚洲在线视频| 午夜影院在线播放| 7m第一福利500精品视频| av老司机在线观看| 97精品国产97久久久久久春色| 欧美6一10sex性hd| 欧美激情精品久久久久久大尺度 | 成人羞羞网站入口| 色就是色欧美| 日本不卡高清| 在线成人av电影| 伊人成综合网| 久久亚洲a v| 一本久道久久综合狠狠爱| 蜜桃传媒一区二区三区| 国产一区91| 久久精品网站视频| 蜜桃精品在线观看| 在线观看av免费观看| 国产91丝袜在线18| 好吊色视频一区二区三区| 99久久久免费精品国产一区二区| 性欧美成人播放77777| 国产人成亚洲第一网站在线播放| 女人十八毛片嫩草av| 日韩美女视频一区二区| 欧美日韩偷拍视频| 欧美性高潮床叫视频| 国语对白做受69按摩| 欧美日韩aaaaa| 亚洲老妇色熟女老太| 国产午夜精品理论片a级探花| 超碰97在线免费观看| 欧美日韩999| 日韩脚交footjobhdboots| 国产精品久久网| 日韩在线观看一区二区三区| 精品人伦一区二区三区| 欧美日韩在线网站| 91视频成人免费| 国产精品色网| 久久精品国产99久久99久久久| 成人精品视频一区二区三区| 国产 欧美 在线| 一区二区在线观看视频| 秋霞精品一区二区三区| 宅男噜噜噜66一区二区66| 午夜视频免费在线| 色偷偷888欧美精品久久久| 免费在线观看av电影| 国产99久久久欧美黑人| 欧美精品影院| 日韩亚洲视频在线| 亚洲国产影院| 色呦色呦色精品| 91最新地址在线播放| 亚洲女人毛茸茸高潮| 精品日韩中文字幕| 91精品视频免费在线观看| 精品视频久久久久久久| sm国产在线调教视频| 国产成人精品久久二区二区91| 欧美欧美在线| 一区二区不卡视频| 麻豆成人在线| 久久久久亚洲AV成人无码国产| 中文字幕在线观看一区| 黄色在线免费观看| 亚洲成色777777女色窝| 黄网页免费在线观看| 日本一区二区在线免费播放| 91综合精品国产丝袜长腿久久| 亚洲一卡二卡三卡| 久久久久久久尹人综合网亚洲| 亚洲成a人无码| 亚洲天堂久久久久久久| 亚洲 小说区 图片区| 精品无码久久久久久国产| 手机在线免费看av| 成人羞羞国产免费| 久久性感美女视频| 成人亚洲视频在线观看| proumb性欧美在线观看| 久久免费视频6| 日韩一区二区三区精品视频| 2019中文字幕在线视频| 国产精品久久久av| 北条麻妃国产九九九精品小说 | 日韩高清免费在线| 国产福利在线免费观看| 99久久精品免费看国产四区| 伊人情人综合网| 三日本三级少妇三级99| 成人免费在线视频| 一级日韩一级欧美| 最近2019中文字幕第三页视频| 欧美美女日韩| 欧美一级爽aaaaa大片| 久久久国产亚洲精品| 99久久久久久久久久| 狠狠躁天天躁日日躁欧美| 亚欧在线观看视频| 57pao精品| 欧美女王vk| 亚洲福利精品视频| 中文字幕欧美激情| 亚洲怡红院av| 久久精品中文字幕电影| 精品国模一区二区三区欧美| 中文字幕精品在线播放| 国产精品一区免费视频| 欧美又粗又大又长| 精品电影一区二区三区 | 国产精品久久久久久久久免费| 国产最新精品| 午夜免费看毛片| 亚洲欧洲中文日韩久久av乱码| 亚洲精品国产av| 性色av一区二区咪爱| 亚洲最大在线| 在线观看免费黄网站| 亚洲欧美日韩系列| 亚洲国产www| 77777少妇光屁股久久一区| 亚洲小说图片视频| 婷婷激情四射五月天| 亚洲三级小视频| 亚洲欧美高清视频| 欧美亚洲国产视频| 欧美丝袜丝交足nylons172| 亚洲妇熟xx妇色黄蜜桃| 午夜精品一区二区三区免费视频 | 日本欧美三级| 99视频在线视频| 亚洲狠狠丁香婷婷综合久久久| 丰满人妻妇伦又伦精品国产| 91精品国产91久久久| 日本电影一区二区| 岛国大片在线免费观看| 色综合久久88色综合天天 | 成人影视亚洲图片在线| 国产成人强伦免费视频网站| 午夜精品一区二区三区电影天堂| 国产视频第一区| 91在线观看网站| 老司机久久99久久精品播放免费| 三级在线观看免费大全| 精品一区二区亚洲| 精品国产伦一区二区三区观看说明| 福利视频一二区| 国产精品国产三级国产普通话蜜臀| 秋霞网一区二区| 国产精品一区av| 国产一区二区三区久久久久久久久| 岛国片在线免费观看| 亚洲第一精品福利| 精品视频在线观看免费观看| 欧美成人xxxxx| 亚洲精选免费视频|