python中的logger模块详细讲解

logger 提供了应用程序可以直接使用的接口
handler将(logger创建的)日志记录发送到合适的目的输出
filter提供了细度设备来决定输出哪条日志记录
formatter决定日志记录的最终输出格式


logging模块介绍

Python的logging模块提供了通用的日志系统,熟练使用logging模块可以方便开发者开发第三方模块或者是自己的Python应用。同样这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP、GET/POST,SMTP,Socket等,甚至可以自己实现具体的日志记录方式。下文我将主要介绍如何使用文件方式记录log。

 

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

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)

 

python:logging模块

10 DECEMBER 2015

概述

python的logging模块(logging是线程安全的)给应用程序提供了标准的日志信息输出接口。logging不仅支持把日志输出到文件,还支持把日志输出到TCP/UDP服务器,EMAIL服务器,HTTP服务器,UNIX的syslog系统等。在logging中主要有四个概念:logger、handler、filter和formatter,下面会分别介绍。


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都配置一遍。


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 soraises 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 bysubclasses."""passdef close(self):"""  Tidy up any resources used by the handler.This version does removes the handler from an internal listof handlers which is closed when shutdown() is called. Subclassesshould 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.stderrself.stream = strmdef flush(self):if self.stream and hasattr(self.stream, "flush"):self.stream.flush()def emit(self, record):try:msg = self.format(record)stream = self.streamfs = "%s\n"if not hasattr(types, "UnicodeType"): #if no unicode support...stream.write(fs % msg)else:try:if (isinstance(msg, unicode) andgetattr(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):raiseexcept:self.handleError(record)


在构造函数中,如果提供了strm参数,那么它就是要输出到的流,如果没提供,那么就会将日志输出到标准错误输出流sys.stderr。 
flush()方法的作用是:刷新self.stream内部的I/O缓冲区。每次emit日志之后都会调用这个方法,将日志从I/O缓冲区sync到self.stream。 
emit(record)方法的作用是:将LogRecord对象(record)记录到self.streamemit(record)方法首先调用基类logging.Handler提供的format(record)方法,该方法会根据设置的Formatter对象来格式化record对象,得到要记录的字符串msg。然后对fsfs其实就是在msg的尾部增加一个换行'\n')进行一系列的编码解码,将它写入到self.stream。最后再刷新self.stream。在emit(record)调用期间发生的异常,应该调用logging.Handler提供的handleError(record)方法来处理。


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。


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.configlogging.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 timelogging.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 structHOST = '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()  

转载于:https://www.cnblogs.com/fmgao-technology/p/9090901.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/283124.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

总在用户态调试 C# 程序,终还是搭了一个内核态环境

一&#xff1a;背景 一直在用 WinDbg 调试用户态程序&#xff0c;并没有用它调试过 内核态&#xff0c;毕竟不是做驱动开发&#xff0c;也没有在分析 dump 中需要接触用内核态的需求&#xff0c;但未知的事情总觉得很酷&#xff0c;加上最近在看 《深入解析 Windows 操作系统》…

CentOS搭建Sqoop环境

Sqoop是一个用来将Hadoop&#xff08;Hive、HBase&#xff09;和关系型数据库中的数据相互转移的工具&#xff0c;可以将一个关系型数据库&#xff08;例如&#xff1a;MySQL ,Oracle ,Postgres等&#xff09;中的数据导入到Hadoop的HDFS中&#xff0c;也可以将HDFS的数据导入到…

bat kafka启动_windows下搭建Kafka,并通过命令窗口收发消息

参考网址&#xff1a;前提条件&#xff1a;windows环境需要安装jdk2.由于Kafka依赖于zookeeper&#xff0c;所以也需要下载zookeeper,可以通过官网下载http://zookeeper.apache.org/3.安装zookeeper将压缩包解压后&#xff0c;到bin目录下&#xff0c;启动zkServer.bat即可注意…

异常处理、socke基于TCP协议编程

一、异常处理 1、错误和异常 1.程序中难免出现错误&#xff0c;而错误分成两种 &#xff08;1&#xff09;语法错误&#xff08;这种错误过不了Python解释器的语法检测&#xff0c;必须在程序执行前改正&#xff09; #语法错误示范一 if#语法错误示范二 def test:pass#语法错误…

getComputedStyle方法的那些事

一、getComputedStyle是&#xff1f;getComputedStyle是一个可以获取当前元素所有最终使用的CSS属性值。返回的是一个CSS样式声明对象([object CSSStyleDeclaration])&#xff0c;只读。 getComputedStyle() gives the final used values of all the CSS properties of an elem…

maven正确的集成命令-U-B

http://healthandbeauty.iteye.com/blog/1618501 在持续集成服务器上使用怎样的 mvn 命令集成项目&#xff0c;这个问题乍一看答案很显然&#xff0c;不就是 mvn clean install 么&#xff1f;事实上比较好的集成命令会稍微复杂些&#xff0c;下面是一些总结&#xff1a; 不要忘…

如何避免 .NET 中 HttpClient 的 DNS 失效问题?

HttpClient 可以用来发送 HTTP 请求。HttpClient 可以设置为单例并在整个生命周期中重复使用。这是因为&#xff0c;HttpClient 有一个“连接池”来重用连接并减少 TCP 连接的数量。因此&#xff0c;如果您向同一主机发送多个请求&#xff0c;它们将重用相同的连接。这样&#…

POJ 1159 Palindrome(字符串变回文:LCS)

POJ 1159 Palindrome(字符串变回文:LCS) http://poj.org/problem?id1159 题意: 给你一个字符串, 问你做少须要在该字符串中插入几个字符能是的它变成一个回文串. 分析: 首先把原字符串和它的逆串进行匹配, 找出最长公共子序列. 那么最长公共子序列的字符串肯定是一个回文串. 所…

java excutorthread_Java中ThreadPoolExecutor的参数理解

一、使用Executors创建线程池之前创建线程的时候都是用的Executors的newFixedThreadPool(),newSingleThreadExecutor(),newCachedThreadPool()这三个方法。当然Executors也是用不同的参数去new ThreadPoolExecutor1. newFixedThreadPool()创建线程数固定大小的线程池。 由于使用…

yii1.0性能调优之改善并发数

开启YII的APC缓存 在config/main.php components 组件下添加&#xff1a; apccache>array(class>system.caching.CApcCache), 下载php_apc.dll&#xff0c;文件放到php/ext 下&#xff0c;搜索时可能会比较麻烦.... 在php.ini 中添加php_apc扩展&#xff1a; extension…

windows下apache报错The requested operation has failed解决方法

2019独角兽企业重金招聘Python工程师标准>>> Apache报错The requested operation has failed&#xff0c;基本上是因为端口被占用。解决方法如下&#xff1a; 第一步&#xff0c;运行cmd&#xff0c;cd 定位到Apache安装目录的bin目录下&#xff0c;输入httpd.exe -…

stm32 usmart使用

我直接用正点原子给的&#xff0c;步骤如下 先添加三个.c进工程&#xff0c;添加两个头文件的编译路径 #include "usart.h"#include "usmart.h" main函数里添加如下 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2 uart_init(960…

Scylla——开源免费的优秀代理 IP 池:自动验证、JSON API、基于 React 的 Web UI、Docker 支持...

GitHub&#xff1a;github.com/imWildCat/s… 中文文档&#xff1a;scylla.wildcat.io/zh/latest/ 自己是一个爬虫爱好者&#xff0c;有时候爬虫写的太过强大了被目标网站封了&#xff08;笑&#xff09;。所以就萌生了用代理 IP 的想法。很可惜很多开源代理 IP 池都是没有持续…

vs2015提示中文

解决方案&#xff1a;1.找到这个目录C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework 进入 \v4.0\zh-Hans的目录&#xff0c;全部复制&#xff0c;覆盖掉\v4.5\zh-Hans就行了

Istio 1.15 发布,支持 arm64 架构处理器

Istio 是基于容器的云原生技术栈的三大核心技术之一&#xff0c;另外两个是 Kubernetes 和 Knative。其中 Kubernetes 和 Knative 早已支持了 arm64 架构&#xff0c;甚至连 Istio 的数据平面 Envoy 早在 1.16 版本 [1] 就已支持 arm64 架构&#xff08;2020 年 10 月&#xff…

TP框架表单验证 【包含ajax方法】

之前的表单验证都是用js写的&#xff0c;这里也可以使用tp框架的验证。但是两者比较而言还是js验证比较好&#xff0c;因为tp框架验证会运行后台代码&#xff0c;这样运行速度和效率就会下降。  自动验证是ThinkPHP模型层提供的一种数据验证方法&#xff0c;可以在使用create创…

Spring 入门学习二之IOC

今天来学习Spring ioc .一、spring jar 包导入 在 spring 官网下载开发包 spring-framework-4.2.4.RELEASE,然后导入需要的 jar 包到项目 /lib/ 目录下。 &#xfffc; 二、代码开发 新建一个 src/cn/sxt/bean/Hello.java文件 package cn.sxt.bean;/*** Created by kaiyiwang o…

java 物理内存_聊聊Java中的内存

JVM的内存先放一张JVM的内存划分图&#xff0c;总体上可以分为堆和非堆(粗略划分&#xff0c;基于java8)那么一个Java进程最大占用的物理内存为&#xff1a;Max Memory eden survivor old String Constant Pool Code cache compressed class space Metaspace Thread st…

.Net CoreRabbitMQ基本使用

队列模式https://www.rabbitmq.com/getstarted.html对以上几种模式进行简要分类&#xff0c;可以分成如下三类(RPC暂不考虑)简单队列模式&#xff0c;单发单收&#xff0c;一对一模式Worker模式&#xff0c;单发多收(一个消息一个接收者&#xff0c;多个消息多个接收者)&#x…

【微信小程序】:实现轮播图3秒滚动

wxml模板&#xff1a;&#xff08;数据一维数组&#xff09; <scroll-view scroll-y"true"><swiper autoplay"auto" interval"3000" duration"500"><block wx:for"{{home_pics}}" wx:for-index"index…