主頁 > 後端開發 > logging日志傳輸

logging日志傳輸

2020-09-22 09:40:58 後端開發

 

1.生成日志并通過http傳輸出去(通過HTTPHandler方式):

#生成并發送日志
import logging
from logging.handlers import HTTPHandler
import logging.config

def save():
    logger = logging.getLogger(__name__)
    # 生成一個log實體,如果括號為空則回傳root logger
    hh = HTTPHandler(host='127.0.0.1:5000', url='/log', method='POST')
    #用HTTPHandler直接發送日志,而并不是寫檔案再傳檔案,
    logger.setLevel(logging.INFO)
    #設定日志最低輸出級別為info
    logger.addHandler(hh)
    #添加Handler物件給記錄器(為logger添加的日志處理器,可以自定義日志處理器讓其輸出到其他地方)
    logger.info('存入600元')  # 輸出日志,內容為‘存入600元’
save()

 

 

2.用flask接收傳過來的日志:

 

#flask接收日志
from flask import Flask,request
app = Flask(__name__)



@app.route('/log',methods=['POST'])
def say_hello():
    #查看傳過來的資料格式:
    print(request.mimetype)
    #HTTPHandler傳過來的是個form表單
    print(request.form.to_dict())
    return '<h1>Hello, Flask!</h1>'


if __name__ == '__main__':
    app.run()


輸出:
#這是傳過來的資料格式,是個form表單
application/x-www-form-urlencoded 

#這是form.to_dict決議出來的內容(直接決議成了字典)
{'name': '__main__', 'msg': '存入600元', 'args': '()', 
'levelname': 'INFO', 'levelno': '20',
'pathname': 'C:/Users/huawei/Desktop/code/log/send_log.py', 'filename': 'send_log.py', 'module': 'send_log',
'exc_info': 'None', 'exc_text': 'None', 'stack_info': 'None', 'lineno': '15', 'funcName': 'save', 'created': '1593581146.172768',
'msecs': '172.76811599731445', 'relativeCreated': '176.5270233154297', 'thread': '13904', 'threadName': 'MainThread',
'processName': 'MainProcess', 'process': '3656'}

 

3.logging模塊介紹

       Python的logging模塊提供了通用的日志系統,熟練使用logging模塊可以方便開發者開發第三方模塊或者是自己的Python應用,同樣這個模塊提供不同的日志級別,并可以采用不同的方式記

錄日志,比如檔案,HTTP、GET/POST,SMTP,Socket等,甚至可以自己實作具體的日志記錄方式,下文我將主要介紹如何使用檔案方式記錄log,

 

1.基本概念:

logging模塊包括logger,handler,filter,formatter這四個基本概念,

logging模塊與log4j的機制是一樣的,只是具體的實作細節不同,模塊提供logger,handler,filter,formatter,

 

logger:提供日志介面,供應用代碼使用,logger最長用的操作有兩類:配置和發送日志訊息,可以通過logging.getLogger(name)獲取logger物件,如果不指定name則回傳root物件,多次使用相

同的name呼叫getLogger方法回傳同一個logger物件,

 

handler:將日志記錄(log record)發送到合適的目的地(destination),比如檔案,socket等,一個logger物件可以通過addHandler方法添加0到多個handler,每個handler又可以定義不同日志

級別,以實作日志分級過濾顯示,

 

filter:提供一種優雅的方式決定一個日志記錄是否發送到handler,

 

formatter:指定日志記錄輸出的具體格式,formatter的構造方法需要兩個引數:訊息的格式字串和日期字串,這兩個引數都是可選的,

與log4j類似,logger,handler和日志訊息的呼叫可以有具體的日志級別(Level),只有在日志訊息的級別大于logger和handler的級別,

 

import logging
logging.basicConfig(level=logging.DEBUG,
    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
    datefmt='%a, %d %b %Y %H:%M:%S',
    filename='myapp.log',
    filemode='w')
#################################################################################################
#定義一個StreamHandler,將INFO級別或更高的日志資訊列印到標準錯誤,并將其添加到當前的日志處理物件#
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)
#################################################################################################
logging.debug('This is debug message')
logging.info('This is info message')
logging.warning('This is warning message')
  
螢屏上列印:
root  : INFO  This is info message
root  : WARNING This is warning message
./myapp.log檔案中內容為:
Sun, 24 May 2009 21:48:54 demo2.py[line:11] DEBUG This is debug message
Sun, 24 May 2009 21:48:54 demo2.py[line:12] INFO This is info message
Sun, 24 May 2009 21:48:54 demo2.py[line:13] WARNING This is warning message

 

2.主要用法:

logging.StreamHandler: 日志輸出到流,可以是sys.stderr、sys.stdout或者檔案

logging.FileHandler: 日志輸出到檔案

日志回滾方式,實際使用時用RotatingFileHandler和TimedRotatingFileHandler

logging.handlers.BaseRotatingHandler

logging.handlers.RotatingFileHandler

logging.handlers.TimedRotatingFileHandler

logging.handlers.SocketHandler: 遠程輸出日志到TCP/IP sockets

logging.handlers.DatagramHandler: 遠程輸出日志到UDP sockets

logging.handlers.SMTPHandler: 遠程輸出日志到郵件地址

logging.handlers.SysLogHandler: 日志輸出到syslog

logging.handlers.NTEventLogHandler: 遠程輸出日志到Windows NT/2000/XP的事件日志

logging.handlers.MemoryHandler: 日志輸出到記憶體中的制定buffer

logging.handlers.HTTPHandler: 通過"GET""POST"遠程輸出到HTTP服務器

 

舉例:

import logging
import sys
# 獲取logger實體,如果引數為空則回傳root logger
logger = logging.getLogger("AppName")
# 指定logger輸出格式
formatter = logging.Formatter('%(asctime)s %(levelname)-8s: %(message)s')
# 檔案日志
file_handler = logging.FileHandler("test.log")
file_handler.setFormatter(formatter) # 可以通過setFormatter指定輸出格式
# 控制臺日志
console_handler = logging.StreamHandler(sys.stdout)
console_handler.formatter = formatter # 也可以直接給formatter賦值
# 為logger添加的日志處理器,可以自定義日志處理器讓其輸出到其他地方
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# 指定日志的最低輸出級別,默認為WARN級別
logger.setLevel(logging.INFO)
# 輸出不同級別的log
logger.debug('this is debug info')
logger.info('this is information')
logger.warn('this is warning message')
logger.error('this is error message')
logger.fatal('this is fatal message, it is same as logger.critical')
logger.critical('this is critical message')
# 2016-10-08 21:59:19,493 INFO : this is information
# 2016-10-08 21:59:19,493 WARNING : this is warning message
# 2016-10-08 21:59:19,493 ERROR : this is error message
# 2016-10-08 21:59:19,493 CRITICAL: this is fatal message, it is same as logger.critical
# 2016-10-08 21:59:19,493 CRITICAL: this is critical message
# 移除一些日志處理器
logger.removeHandler(file_handler)

 

4.概述:

       python的logging模塊(logging是執行緒安全的)給應用程式提供了標準的日志資訊輸出介面,logging不僅支持把日志輸出到檔案,還支持把日志輸出到TCP/UDP服務器,EMAIL服務器,

HTTP服務器,UNIX的syslog系統等,在logging中主要有四個概念:logger、handler、filter和formatter,下面會分別介紹,

 

1.logger

Logger物件扮演了三重角色:

它給應用程式暴漏了幾個方法,以便應用程式能在運行時記錄日志,

Logger物件根據日志的級別或根據Filter物件,來決定記錄哪些日志,

Logger物件負責把日志資訊傳遞給相關的handler,

在Logger物件中,最常使用的方法分為兩類:configuration,message sending, configuration方法包括:

setLevel(level)

setLevel(level)方法用來設定logger的日志級別,如果日志的級別低于setLevel(level)方法設定的值,那么logger不會處理它,

logging模塊內建的日志級別有:

CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0 (數值越大級別越高)
addFilter(filter)
removeFilter(filter)
addHandler(handler)
removeHandler(handler)

 

 

message sending方法包括:

debug(log_message, [*args[, **kwargs]])

使用DEBUG級別,記錄log_message % args,

 

為了記錄例外資訊,需要將關鍵字引數exc_info設定為一個true值,

logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
info(log_message, [*args[, **kwargs]])

 

使用INFO級別,記錄log_message % args,

為了記錄例外資訊,需要將關鍵字引數exc_info設定為一個true值,

logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
warning(log_message, [*args[, **kwargs]])

 

使用WARNING級別,記錄log_message % args,

為了記錄例外資訊,需要將關鍵字引數exc_info設定為一個true值,

logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
error(log_message, [*args[, **kwargs]])

 

使用Error級別,記錄log_message % args,

為了記錄例外資訊,需要將關鍵字引數exc_info設定為一個true值,

logger.error("Houston, we have a %s", "major problem", exc_info=1)
critical(log_message, [*args[, **kwargs]])

 

使用CRITICAL級別,記錄log_message % args,

為了記錄例外資訊,需要將關鍵字引數exc_info設定為一個true值,

logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
exception(message[, *args]) 
self.error(*((msg,) + args), **{'exc_info': 1})
log(log_level, log_message, [*args[, **kwargs]])

 

使用整型的級別level,記錄log_message % args,

為了記錄例外資訊,需要將關鍵字引數exc_info設定為一個true值,

logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
logging.getLogger([name])

 

方法回傳一個Logger實體的參考,如果提供了name引數,那么它就是這個Logger實體的名稱,如果沒提供name引數,那么這個Logger實體的名稱是root,

可以通過Logger實體的name屬性,來查看Logger實體的名稱,

Logger實體的名稱是使用句號(.)分隔的多級結構,

在這種命名方式中,后面的logger是前面的logger的子(父子logger只是簡單的通過命名來識別),比如:有一個名稱為foo的logger,那么諸如foo.bar、foo.bar.baz和foo.bam這樣的logger都是foo

這個logger的子logger,

子logger會自動繼承父logger的定義和配置,

使用相同的名稱多次呼叫logging.getLogger([name])方法,會回傳同一個logger物件的參考,

這個規則不僅僅在同一個module有效,而且對在同一個Python解釋器行程的多個module也有效,

因此應用程式可以在一個module中定義一個父logger,然后在其他module中繼承這個logger,而不必把所有的logger都配置一遍

 

2.handler

handler實體負責把日志事件分發到具體的目的地,logger物件可以使用addHandler()方法,添加零個或多個handler物件到它自身,一個常見的場景是:應用程式可能希望把所有的日志都記錄到一

個log檔案,所有的ERROR及以上級別的日志都記錄到stdout,所有的CRITICAL級別的日志都發送到一個email地址,這個場景需要三個獨立的handler,每個handler負責把特定級別的日志發送到

特定的地方,

 

下面是logging模塊內置的handler:

StreamHandler FileHandler RotatingFileHandler TimedRotatingFileHandler SocketHandler DatagramHandler SysLogHandler NTEventLogHandler SMTPHandler MemoryHandler HTTPHandler

 

內置的handler提供了下面的配置方法:

setLevel(level)

handler物件的setLevel()方法,與logger物件的setLevel()方法一樣,也是用于設定一個日志級別,如果日志的級別低于

setLevel()方法設定的值,那么handler不會處理它,

setFormatter(formatter)

addFilter(filter)

removeFilter(filter)

應用程式代碼不應該直接實體化和使用handler,logging.Handler是一個定義了所有的handler都應該實作的介面和建立了子類能夠使用(或重寫)的一些默認行為的基類,

自定義Handler 自定義的handler必須繼承自logging.Handler,且實作下面的方法:

class Handler(Filterer): 
 def emit(self, record):
  """
  Do whatever it takes to actually log the specified logging record.
  This version is intended to be implemented by subclasses and so
  raises a NotImplementedError.
  """
  raise NotImplementedError, 'emit must be implemented '\
         'by Handler subclasses'
 def flush(self):
  """
  Ensure all logging output has been flushed.
  This version does nothing and is intended to be implemented by
  subclasses.
  """
  pass
 def close(self):
  """ 
  Tidy up any resources used by the handler.
  This version does removes the handler from an internal list
  of handlers which is closed when shutdown() is called. Subclasses
  should ensure that this gets called from overridden close()
  methods.
  """
  #get the module data lock, as we're updating a shared structure.
  _acquireLock()
  try: #unlikely to raise an exception, but you never know...
   if self in _handlers:
    del _handlers[self]
   if self in _handlerList:
    _handlerList.remove(self)
  finally:
   _releaseLock()

其中,emit(record)方法負責執行真正地記錄日志所需的一切事情,在logging.Handler的子類中必須實作這個方法,close()方法負責清理handler所使用的資源(在Python解釋器退出的時候,會調

用所有的handler的flush()和close()方法),logging.Handler的子類應該確保在重寫close()方法的時候,呼叫父類的該方法,

 

下面分析logging.StreamHandler的源代碼:

class StreamHandler(Handler): 
 def __init__(self, strm=None):
  Handler.__init__(self)
  if strm is None:
   strm = sys.stderr
  self.stream = strm
 def flush(self):
  if self.stream and hasattr(self.stream, "flush"):
   self.stream.flush()
 def emit(self, record):
  try:
   msg = self.format(record)
   stream = self.stream
   fs = "%s\n"
   if not hasattr(types, "UnicodeType"): #if no unicode support...
    stream.write(fs % msg)
   else:
    try:
     if (isinstance(msg, unicode) and
      getattr(stream, 'encoding', None)):
      fs = fs.decode(stream.encoding)
      try:
       stream.write(fs % msg)
      except UnicodeEncodeError:
       #Printing to terminals sometimes fails. For example,
       #with an encoding of 'cp1251', the above write will
       #work if written to a stream opened or wrapped by
       #the codecs module, but fail when writing to a
       #terminal even when the codepage is set to cp1251.
       #An extra encoding step seems to be needed.
       stream.write((fs % msg).encode(stream.encoding))
     else:
      stream.write(fs % msg)
    except UnicodeError:
     stream.write(fs % msg.encode("UTF-8"))
   self.flush()
  except (KeyboardInterrupt, SystemExit):
   raise
  except:
   self.handleError(record)

在建構式中,如果提供了strm引數,那么它就是要輸出到的流,如果沒提供,那么就會將日志輸出到標準錯誤輸出流sys.stderr,

flush()方法的作用是:重繪self.stream內部的I/O緩沖區,每次emit日志之后都會呼叫這個方法,將日志從I/O緩沖區sync到self.stream,

emit(record)方法的作用是:將LogRecord物件(record)記錄到self.stream,emit(record)方法首先呼叫基類logging.Handler提供的format(record)方法,該方法會根據設定的Formatter物件來格式

化record物件,得到要記錄的字串msg,然后對fs(fs其實就是在msg的尾部增加一個換行'\n')進行一系列的編碼解碼,將它寫入到self.stream,最后再重繪self.stream,在emit(record)呼叫期

間發生的例外,應該呼叫logging.Handler提供的handleError(record)方法來處理,

 

 

3.filter

Filter物件用于對LogRecord物件執行過濾,logger和handler都可以使用filter來過濾record,下面用一個列子來說明Filter基類的作用:

如果使用A.B實體化一個filter,那么它允許名稱為A.B,A.B.C,A.B.C.D這樣的logger記錄的日志通過,不允許名稱為A.BB,B.A.B這樣的logger記錄的日志通過,

如果使用空字串實體化一個filter,那么它允許所有的事件通過,

 

Filter基類有一個方法叫filter(record),它用來決定指定的record(LogRecord物件)是否被記錄,如果該方法回傳0,則不記錄record;回傳非0則記錄record,

Filterer(注意:不是Filter)是logger和handler的基類,它提供了方法來添加和洗掉filter,并且提供了filter(record)方法用于過濾record,該方法默認允許record被記錄,但是任何filter都可以否決這

個默認行為,如果想要丟棄record,filter(record)方法應該回傳0,否則應該回傳非0,

 

4.formatter

Formatter物件用于把一個LogRecord物件轉換成文本,它定義了日志的格式、結構,與logging.Handler類不同,應用程式可以直接實體化Formatter類,如果需要也可以子類化Formatter,以便定

制一些行為,

Formatter的建構式接受兩個引數:第一個引數是用于日志資訊的格式化字串;第二個引數是用于日期的格式化字串,第二個引數可選的,默認值是%Y-%m-%d %H:%M:%S,

日志資訊的格式化字串用%(<dictionary key>)s風格的字串做替換,

下面是替換字串和它們所代表的含義:

%(name)s
logger的名稱
%(levelno)s
日志級別的數字表現形式
%(levelname)s
日志級別的文本表現形式
%(pathname)s
呼叫logging的源檔案的全路徑名
%(filename)s
pathname的檔案名部分
%(module)s
模塊名(filename的名稱部分)
%(lineno)d
呼叫logging的行號
%(funcName)s
函式名
%(created)f
LogRecord的創建時間(time.time()的回傳值)
%(asctime)s
LogRecord的創建時間的文本表現形式
%(msecs)d
創建時間的毫秒部分
%(relativeCreated)d 
LogRecord的創建時間,單位是毫秒,這個時間是相對logging模塊被加載的時間的(通常就是應用程式啟動的時間),
%(thread)d
執行緒ID
%(threadName)s
執行緒名稱
%(process)d
行程ID
%(message)s
record.getMessage()的回傳結果,

 

舉例:

配置logging

下面是一個簡單的例子,它會向標準輸出列印日志:

import logging 
import sys 
logger = logging.getLogger(__name__) 
filter = logging.Filter(__name__) 
formatter = logging.Formatter("%(asctime)s|%(name)-12s|%(message)s", "%F %T")
stream_handler = logging.StreamHandler(sys.stdout) 
stream_handler.addFilter(filter) 
stream_handler.setLevel(logging.DEBUG) 
stream_handler.setFormatter(formatter)
logger.setLevel(logging.DEBUG) 
logger.addFilter(filter) 
logger.addHandler(stream_handler)
if __name__ == "__main__": 
 logger.info("info")

運行這個腳本,輸出結果是:

2015-12-16 13:52:17|__main__ |info

 

 

使用組態檔,配置logging

下面是一個使用組態檔,配置logging的例子:

import logging 
import logging.config
logging.config.fileConfig("logging.conf")
if __name__ == "__main__": 
 logger = logging.getLogger("test_logging.sublogger")
 logger.info("info")

 

logging.conf如下:

[loggers]
keys = root,logger
[handlers]
keys = stream_handler
[formatters]
keys = formatter
[logger_root]
handlers = stream_handler
[logger_logger]
handlers = stream_handler 
level = DEBUG 
propagate = 1 
qualname = test_logging
[handler_stream_handler]
class = StreamHandler 
args = (sys.stdout,) 
formatter = formatter 
level = DEBUG
[formatter_formatter]
format = %(asctime)s|%(name)-12s|%(message)s 
datefmt = %F %T 

需要解釋的地方有兩處:第一個是logger_xxxsection中的propagate選項,在logger物件把record傳遞給所有相關的handler的時候,會(逐級向上)尋找這個logger和它所有的父logger的全部

handler,在尋找程序中,如果logger物件的propagate屬性被設定為1,那么就繼續向上尋找;如果某個logger的propagate屬性被設定為0,那么就會停止搜尋,

第二個是logger_xxxsection中的qualname選項,它其實就是logger的名稱,

使用組態檔的時候,必須定義root logger,

 

最酷的listen(port)函式

logging.config.listen(port)函式可以讓應用程式在一個socket上監聽新的配置資訊,達到在運行時改變配置,而不用重啟應用程式的目的,

監聽程式:

import logging.config 
import logging 
import time
logging.config.fileConfig("logging.conf") 
logger = logging.getLogger("test_logging.listen")
t = logging.config.listen(9999) 
t.setDaemon(True) 
t.start()
try: 
 while True:
  logger.info('running.')
  time.sleep(3)
except (KeyboardInterrupt, SystemExit, Exception): 
 logging.config.stopListening()

 

發送新的配置資訊程式:

import socket 
import struct
HOST = 'localhost' 
PORT = 9999 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.connect((HOST, PORT)) 
print "connected..." 
data_to_send = open("logging.conf").read() 
s.send(struct.pack(">L", len(data_to_send))) 
s.send(data_to_send) 
print "closing..." 
s.close() 

 

5.日志模塊化輸出

import time
import os
from logging import handlers

base_path = os.path.dirname(os.path.abspath(__file__)) #C:\Users\33101\Desktop\敲代碼\logg
# print('當前目錄絕對路徑:',base_path)
# b=os.path.join(base_path,'a.txt')
# print(b)
log_file_path=os.path.join(base_path,'日志檔案12345678')



os.makedirs(log_file_path, exist_ok=True)
def _logging(**kwargs):
    level = kwargs.pop('level', None)
    filename = kwargs.pop('filename', None)
    datefmt = kwargs.pop('datefmt', None)
    format = kwargs.pop('format', None)
    if level is None:
        level = logging.DEBUG #記錄日志的等級
    if filename is None:
        filename = 'default.log' #默認日志生成的檔案名字
    if datefmt is None: #時間格式
        datefmt = '%Y-%m-%d %H:%M:%S'
    if format is None: #日志記錄的內容
        format = '發生時間:%(asctime)s  所在檔案:[%(module)s]  日志等級:%(levelname)s  代碼運行行數: [%(lineno)d] 具體資訊: %(message)s'

    log = logging.getLogger(filename)
    format_str = logging.Formatter(format, datefmt)#日志
    # backupCount 保存日志的數量,過期自動洗掉
    # when 按什么日期格式切分(這里方便測驗使用的秒),when=s時是按照秒分檔案寫日志,when=d時是按照天分檔案寫日志
th = handlers.TimedRotatingFileHandler(filename=filename, when='s', encoding='utf-8') th.setFormatter(format_str) th.setLevel(logging.INFO) log.addHandler(th) log.setLevel(level)#設定記錄日志的等級 return log logger = _logging(filename=os.path.join(log_file_path,'log1.txt')) count=50 if __name__ == '__main__': count=50 while count: # time.sleep(0.1) # logger.info('哈哈哈') count-=1 time.sleep(1) # logger.info('1哈哈哈') # logger.info('1哈哈哈') logger.info('1哈哈哈') # time.sleep(1) # logger.info('2哈哈哈') # logger.info('2哈哈哈') logger.info('2哈哈哈') # time.sleep(1) # logger.info('3哈哈哈') logger.info('3哈哈哈') logger.debug('3哈哈哈') # time.sleep(4) logger.error('4哈哈哈')

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/103797.html

標籤:Python

上一篇:一文說通MongoDB via Python操作

下一篇:112買賣股票的最佳時機II

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more