python程序员招聘闲暇上什么网站

最近 Python 有点火? 给 Web 程序员 7 个学习它的理由!
Python 是一门更注重可读性和效率的语言,尤其是相较于 Java,PHP 以及 C++ 这样的语言,它的这两个优势让其在开发者中大受欢迎。
诚然,它有点老了,但仍是80后啊 —— 至少没有 Cobol 或者 Fortran 那么老。而且,如果还能派上用场的话,为啥要折腾着改变它呢 (尤其在这个还有那么多方法可以提升它性能的时候)?
实际上这要看你怎么看待它,生命线长本身就是件好事 —— 说明它稳定且可靠。
如果你是像其他许多人一样都是从 Java,C 或者 Perl 开始进入职业生涯的,那么学习 Python 的曲线基本上是不存在的。然而也正是由于 Python 易于上手这一事实,让有些人没有意识到 Python 也应该是一项必要的编程技能。
我要向各位坦诚,我对 Python 的喜爱也是从几年以前才开始的。不经历长期的痛苦教训,我们是不会对这门语言以及它的平台所提供的一切心生感激的。我写下这篇短文的目的就是要将你从同样的痛苦中拯救出来,让你明白为什么需要去了解 Python。
Python 易于学习
好吧,相较于其它许多你可以拿来用的编程语言而言,它“更容易一些”。Python 的语言没有多少仪式化的东西,所以就算不是一个 Python 专家,你也能读懂它的代码。我的经验是,通过实例来学习和教授 Python 要比采取同样的方式去接触比方说 Ruby 或者 Perl 更加容易,因为 Python 的语法里面条条框框以及特殊的处理场景要少得多。 它所专注的并非语言表现的丰富程度,而是你想要用你的代码完成什么。
它能用少量的代码构建出很多功能
Python 能带给所有开发者一种快速的学习体验。通过实践,你可以在最多两天之内轻松实现一个具备基础功能的游戏 (而这还是在对编程完全不了解的情况下)。
另外一些让 Python 成为一门引人注目的编程语言的因素就是它的可读性和高效性。
Python 多才多艺
Python 今年 28 岁了。尽管它比我的许多读者年纪还要大,但是仍然受到高度的关注,因为它可以被应用于如今你所能想得到的相当多的软件开发和操作场景。要管理本地或者云基础设施吗?Python可以。开发网站?OK,它也能行的。需要处理一个 SQL 数据库?可以。需要为 Hive 或者 Pig 定制一个功能?能做到。只是想为自己构建一个小工具?Python 就是最好的选择。需要一门支持面向对象设计的语言?Python 的特性就能满足啦。简而言之,将 Python 了解得更加深入一点点,就能让你具备可以适应范围更宽泛的工作角色的技能。
Python 拥有最成熟的程序包资源库之一
一旦你了解了该语言,就可以利用上这个平台。Python 以 PyPI (读作 Pie-Pie,可以从这里在线进行了解)为其后盾, 这是一个拥有超过 85,000 个 Python 模块和脚本的资源库,你拿过来就立马可以使用。这些模块向你的本地 Python 环境分发已经预先打包好的功能,可以用来解决各种诸如数据库处理,计算机视觉实现,像维度分析这样的高级数据分析的执行,或者是构建 REST 风格的 web 服务这些问题。
Python 广泛用于数据科学领域
不管你从事的是什么工作,数据都会是其中的一部分。IT,软件开发,市场等等 —— 它们都深度地关乎数据且对于智慧求之若渴。很快数据分析技能就会像编码技能一样的重要,而 Python 在两个领域都占有重要的地位。Python 紧挨着 R 语言,都是现代数据科学中最常被使用的语言。事实上,在数据科学领域,Python 的职位职位需求超过了 R 语言。你在学习 Python 时发展出来的技能将会直接转换并被用来构建起自己的这些分析技能。
Python 是跨平台且开源的
Python 可以跨平台运行,并且已经开放源代码超过20年的时间了,如果你需要代码能同时在Linux,Windows 以及 macOS 上跑起来,Python 就能满足要求。此外,有数十年的修修补补以及不断完善做后盾,可以确保你能够随心所欲地运行自己的代码。
Python 很灵活
有一些Python同其它编程语言集成在一起的稳定实现。
CPython, 同 C 集成的版本。
Jython, 同 Java 集成的Python版本。
IronPython, 被设计用来兼容 .Net 和 C#。
PyObjc, ObjectiveC 工具下的 Python 写法。
RubyPython, 同 Ruby 集成的 Python 版本。
并没有很多的语言能提供像 Python 这样的多样性和简洁性; 能持续努力演进并让社区繁荣好几十年的就更少了。无论你是编码新手还是能信手写就脚本的大师,都需要了解一下 Python。
来自:开源中国社区
https://www.oschina.net/translate/7-reasons-you-should-learn-python-now
原文链接:
https://www.oschina.net/translate/7-reasons-you-should-learn-python-now
本文转自:Web开发
本公众号旨在分享大数据行业领域前沿资讯和观点,内容转载自其他公众号或网站,除确实无法确认,我们都会注明作者和来源,部分文章推送时可能未能及时与原作者取得联系。若涉及版权问题,烦请联系删除。
责任编辑:
声明:本文由入驻搜狐号的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。
今日搜狐热点每个程序员都应该学习使用Python或Ruby
如果你是个学生,你应该会C,C++和Java。还会一些VB,或C#/.NET。多少你还可能开发过一些Web网页,你知道一些HTML,CSS和JavaScript知识。总体上说,我们很难发现会有学生显露出掌握超出这几种语言范围外的语言的才能。这真让人遗憾,因为还有很多种编程语言,它们能让你成为一个更好的程序员。
在这篇文章里,我将会告诉你,为什么你一定要学习Python或Ruby语言。
跟C/C++/Java相比 & Python/Ruby能让你用少的多的多的代码写出相同的程序。有人计算过,Python或Ruby写出的程序的代码行数只相当于相对应的Java代码的行数的五分之一。如果没有绝对的必要,为什么要花这么多时间写出这么多的代码呢?而且,有人说,一个优秀的程序员能维护的代码量最多是2万行。这不区分用的语言究竟是汇编,C还是Python/Ruby/PHP/Lisp。所以,如果你用Python/Ruby写,你一个人干的,不管是干什么,如果换用Java/C/C++,那都需要一个5人的小团队来干。
跟VB/PHP比较 & 跟PHP/VB相比,Python/Ruby的是一种从设计上讲比它们好的不知多少倍的语言。PHP和VB分别是在开发网站和桌面应用程序上非常流行的语言。它们流行的原因是非常的易学。不懂计算机的人也很容易的上手。如果你用这些语言开发过大型的项目,你就会发现这些语言的设计是如此的糟糕。是朋友,他就不会劝你使用PHP/VB。
跟Lisp/Scala/Haskell/Closure/Erlang相比 & Python/Ruby跟它们比起来显得相当的&主流&。确实,这些语言每种都有其很酷的特征,对于高级编程人员,了解这些语言能给他们对编程的思考带来实际的提升。但这些应该在你以后的职业生涯中才去决定学哪一两种。对于现在,Python/Ruby是在语言功能和实际运用之间平衡后的更好的选择。
跟Perl相比 & Python和Ruby都受恩于Perl,在这两种语言异军突起前,Perl是最好、最大的一种动态语言。但现在,Perl已是明日黄花,越来越多的人转向Ruby/Python。我感觉Perl的面向对象机制有点做作,很不好用。通常认为,Perl一种比较难学的语言,因为它提供你了太多不同的方法去完成同一个任务,它的语法有点像密码,非常不直观 & 除非你对它掌握的非常好。总之,我感觉Perl是一种对于学生来说不是很合适的语言&除非你有特殊的理由去学它(例如,你有很多正则表达式要处理,这是Perl的闪光点)。
跟sh/sed/awk/bash相比 & 如果你使用Linux/Unix,你可能需要做一些shell编程,甚至会编写一些不小的程序。但是,对于这些语言,一旦程序达到一定的行数,事情就会开始变得让你痛苦不堪,你最好是用Python去做这些事情。当然,做这种事情,Perl是最好的选择,Python排第二。(Ruby对于系统shell脚本不是很合适)。
你可以在Google上搜一下&为什么X比Y好& & 其中把X换成Python或Ruby,把Y换成另外一种语言 & 你就会发现,有无数的文章来说明它们为什么这么好。
如果你有选择你的毕业设计使用的编程语言的自由,你应该选择Python或Ruby,它们能让你在开发项目的过程中节省一半的时间(除非你要开发的是移动应用,这样你必须要使用Java或Objective-C)。
下面是xkcd上的一幅漫画,告诉你掌握Python后你会变得多么的强大:
如何去学它们呢?很多很多的网站上都提供了学习Python和Ruby的教材和课程。下面的是我从中选出的一些:
,学习Python的好资源。
,学习Ruby的一个好网站。
有疑问吗?请在评论了写出来,我会尽量回答你们。
1:我的这篇文章可能会让很多Perl爱好者很郁闷,现在回味一下,我认识到对这种语言的要求过于苛刻了。因此,我把关于Perl的一节改写了一下。
Python和Ruby都受恩于Perl,在这两种语言出现之前,Perl是最大、最好的动态语言。但Perl现在太老了。它的面向对象性不完整。它很久没有升级更新了,它的市场份额正在丢失。对于一些新的、很火的事物(例如Web编程框架,Web API),它不如Python & Ruby 那样能跟上时代的步伐。基本上,Python/Ruby在兴起,Perl在衰退。
2:本文中的所有语言的比较都是用来给印度计算机科学专业的学生选编程语言时做参考的。像&X比Y好&这样的句子准确的讲是毫无意义的,因为所有的语言都是经过时间的考验而存活下来的,有些语言会在某些领域比另外一种要强,这也是它们存活下来的原因。换句话说,总有一些情况下,PHP/Java/C/C++/Perl 看起来会比 Ruby/Python 等其它语言显的更适合。
想学Python?可查看站长之家的
最新图文推荐
最新专栏文章
大家感兴趣的内容
网友热评的文章
seajs.config({
base: "/resource/passapi/scripts/"
seajs.use('seajs/seajs-css');
seajs.use(['artdialog/src/dialog-plus'], function (dialog) {
$('#favorite').on('click', function(){
$.getJSON('/passapi.ashx?op=userstatus&callback=?', function(data){
if (data.status == 1) {
var _this = $('#favorite').find('span');
$.getJSON('/?app=favorite&controller=favorite&action=add&jsoncallback=?&contentid='+contentid, function(json){
if(json.state){
_this.html('每个 Python 程序员都要知道的日志实践 - Python - 伯乐在线
& 每个 Python 程序员都要知道的日志实践
在现实生活中,记录日志非常重要。银行转账时会有转账记录;飞机飞行过程中,会有黑盒子(飞行数据记录器)记录飞行过程中的一切。如果有出现什么问题,人们可以通过日志数据来搞清楚到底发生了什么。
对于系统开发、调试以及运行,记录日志都是同样的重要。如果没有日志记录,程序崩溃时你几乎就没办法弄明白到底发生了什么事情。举个例子,当你在写一个服务器程序时,记录日志是非常有必要的。下面展示的就是
服务器的日志文件截图。
服务崩溃后,如果没有日志,我几乎没办法知道到底发生了错误。日志不仅对于服务器很重要,对于桌面图形应用同样十分重要。比如,当你的客户的 PC 机程序崩溃时,你可以让他们把日志文件发给你,这样你就可以找到问题到底出在哪儿。相信我,在不同的 PC 环境下,你永远不会知道会有怎样奇怪的问题。我曾经就接收到过这样的错误日志。
17:52:54,828 - root - ERROR - [Errno 10104] getaddrinfo failed
Traceback (most recent call last):
File "&string&", line 124, in main
File "&string&", line 20, in __init__
File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/wx._core", line 7978, in __init__
File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/wx._core", line 7552, in _BootstrapApp
File "&string&", line 84, in OnInit
File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/twisted.internet.wxreactor", line 175, in install
File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/twisted.internet._threadedselect", line 106, in __init__
File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/twisted.internet.base", line 488, in __init__
File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/twisted.internet.posixbase", line 266, in installWaker
File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/twisted.internet.posixbase", line 74, in __init__
File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/socket", line 224, in meth
gaierror: [Errno 10104] getaddrinfo failed
1234567891011121314
2011-08-22 17:52:54,828 - root - ERROR - [Errno 10104] getaddrinfo failedTraceback (most recent call last):&&File "&string&", line 124, in main&&File "&string&", line 20, in __init__&&File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/wx._core", line 7978, in __init__&&File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/wx._core", line 7552, in _BootstrapApp&&File "&string&", line 84, in OnInit&&File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/twisted.internet.wxreactor", line 175, in install&&File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/twisted.internet._threadedselect", line 106, in __init__&&File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/twisted.internet.base", line 488, in __init__&&File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/twisted.internet.posixbase", line 266, in installWaker&&File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/twisted.internet.posixbase", line 74, in __init__&&File "h:workspaceprojectbuildpyi.win32mrdjoutPYZ1.pyz/socket", line 224, in methgaierror: [Errno 10104] getaddrinfo failed
我最终发现,这个客户的 PC 机被一种病毒感染,导致了调用 gethostname 函数失败。看吧,如果没有日志可以查你怎么可能知道这些。
打印输出不是个好办法
尽管记录日志非常重要,但是并不是所有的开发者都能正确地使用它。我曾看到一些开发者是这样记录日志的,在开发的过程中插入 print 语句,开发结束后再将这些语句移除。就像这样:
print 'Start reading database'
records = model.read_recrods()
print '# records', records
print 'Updating record ...'
model.update_records(records)
print 'done'
print 'Start reading database'records = model.read_recrods()print '# records', recordsprint 'Updating record ...'model.update_records(records)print 'done'
这种方式对于简单脚本型程序有用,但是如果是复杂的系统,你最好不要使用这样的方式。首先,你没办法做到在日志文件中只留下极其重要的消息。你会看到大量的消息日志。但是你却找不到任何有用的信息。你除了移除这输出语句这外,没别的办法控制代码,但是极有可能的是你忘记了移出那些没用的输出。再者,print 输出的所有信息都到了标准输出中,这将严重影响到你从标准输出中查看其它输出数据。当然,你也可以把消息输出到 stderr ,但是用 print 做日志记录的方式还是不好。
使用 python 的标准日志模块
那么,怎么样记录日志才是正确的呢?其实非常简单,使用 python 的标准日志模块。多亏 python 社区将日志做成了一个标准模块。它非常简单易用且十分灵活。你可以像这样使用日志系统:
import logging
logging.basicConfig()
logger = logging.getLogger(__name__)
('Start reading database')
# read database here
records = {'john': 55, 'tom': 66}
logger.debug('Records: %s', records)
('Updating records ...')
# update records here
('Finish updating records')
12345678910111213
import logginglogging.basicConfig(level=logging.INFO)logger = logging.getLogger(__name__)&logger.info('Start reading database')# read database here&records = {'john': 55, 'tom': 66}logger.debug('Records: %s', records)logger.info('Updating records ...')# update records here&logger.info('Finish updating records')
运行的时候就可看到:
INFO:__main__:Start reading database
INFO:__main__:Updating records ...
INFO:__main__:Finish updating records
INFO:__main__:Start reading databaseINFO:__main__:Updating records ...INFO:__main__:Finish updating records
你可能会问这与使用 print 有什么不同呢。它有以下的优势:
你可以控制消息的级别,过滤掉那些并不重要的消息。
你可决定输出到什么地方,以及怎么输出。
有许多的重要性别级可供选择,debug、info、warning、error 以及 critical。通过赋予 logger 或者 handler 不同的级别,你就可以只输出错误消息到特定的记录文件中,或者在调试时只记录调试信息。让我们把 logger 的级别改成 DEBUG 再看一下输出结果:
logging.basicConfig(level=logging.DEBUG)
logging.basicConfig(level=logging.DEBUG)
输出变成了:
INFO:__main__:Start reading database
DEBUG:__main__:Records: {'john': 55, 'tom': 66}
INFO:__main__:Updating records ...
INFO:__main__:Finish updating records
INFO:__main__:Start reading databaseDEBUG:__main__:Records: {'john': 55, 'tom': 66}INFO:__main__:Updating records ...INFO:__main__:Finish updating records
正如看到的那样,我们把 logger 的等级改为 DEBUG 后,调试记录就出现在了输出当中。你也可以选择怎么处理这些消息。例如,你可以使用 FileHandler 把记录写进文件中:
import logging
logger = logging.getLogger(__name__)
# create a file handler
handler = logging.FileHandler('hello.log')
# create a logging format
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
# add the handlers to the logger
logger.addHandler(handler)
('Hello baby')
1234567891011121314151617181920
import logging&logger = logging.getLogger(__name__)logger.setLevel(logging.INFO)&# create a file handler&handler = logging.FileHandler('hello.log')handler.setLevel(logging.INFO)&# create a logging format&formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')handler.setFormatter(formatter)&# add the handlers to the logger&logger.addHandler(handler)&logger.info('Hello baby')
标准库模块中提供了许多的 handler ,你可以将记录发送到邮箱甚至发送到一个远程的服务器。你也可以实现自己的记录 handler 。这里将不具体讲述实现的细节,你可以参考官方文档:、 与 。
以合适的等级输出日志记录
有了灵活的日志记录模块后,你可以按适当的等级将日志记录输出到任何地方然后配置它们。那么你可能会问,什么是合适的等级呢?在这儿我将分享一些我的经验。
大多数的情况下,你都不想阅读日志中的太多细节。因此,只有你在调试过程中才会使用 DEBUG 等级。我只使用 DEBUG 获取详细的调试信息,特别是当数据量很大或者频率很高的时候,比如算法内部每个循环的中间状态。
def complex_algorithm(items):
for i, item in enumerate(items):
# do some complex algorithm computation
logger.debug('%s iteration, item=%s', i, item)
def complex_algorithm(items):&&&&for i, item in enumerate(items):&&&&&&&&# do some complex algorithm computation&&&&&&&&&logger.debug('%s iteration, item=%s', i, item)
在处理请求或者服务器状态变化等日常事务中,我会使用 INFO 等级。
def handle_request(request):
('Handling request %s', request)
# handle request here
result = 'result'
('Return result: %s', result)
def start_service():
('Starting service at port %s ...', port)
service.start()
('Service is started')
1234567891011
def handle_request(request):&&&&logger.info('Handling request %s', request)&&&&# handle request here&&&&&result = 'result'&&&&logger.info('Return result: %s', result)&def start_service():&&&&logger.info('Starting service at port %s ...', port)&&&&service.start()&&&&logger.info('Service is started')
当发生很重要的事件,但是并不是错误时,我会使用 WARNING 。比如,当用户登录密码错误时,或者连接变慢时。
def authenticate(user_name, password, ip_address):
if user_name != USER_NAME and password != PASSWORD:
logger.warn('Login attempt to %s from IP %s', user_name, ip_address)
return False
# do authentication here
def authenticate(user_name, password, ip_address):&&&&if user_name != USER_NAME and password != PASSWORD:&&&&&&&&logger.warn('Login attempt to %s from IP %s', user_name, ip_address)&&&&&&&&return False&&&&# do authentication here
有错误发生时肯定会使用 ERROR 等级了。比如抛出异常,IO 操作失败或者连接问题等。
def get_user_by_id(user_id):
user = db.read_user(user_id)
if user is None:
logger.error('Cannot find user with user_id=%s', user_id)
return user
return user
def get_user_by_id(user_id):&&&&user = db.read_user(user_id)&&&&if user is None:&&&&&&&&logger.error('Cannot find user with user_id=%s', user_id)&&&&&&&&return user&&&&return user
我很少使用 CRITICAL 。当一些特别糟糕的事情发生时,你可以使用这个级别来记录。比方说,内存耗尽,磁盘满了或者核危机(希望永远别发生 :S)。
使用 __name__ 作为 logger 的名称
虽然不是非得将 logger 的名称设置为 __name__ ,但是这样做会给我们带来诸多益处。在 python 中,变量 __name__ 的名称就是当前模块的名称。比如,在模块 “foo.bar.my_module” 中调用 logger.getLogger(__name__) 等价于调用logger.getLogger(“foo.bar.my_module”) 。当你需要配置 logger 时,你可以配置到 “foo” 中,这样包 foo 中的所有模块都会使用相同的配置。当你在读日志文件的时候,你就能够明白消息到底来自于哪一个模块。
捕捉异常并使用 traceback 记录它
出问题的时候记录下来是个好习惯,但是如果没有 traceback ,那么它一点儿用也没有。你应该捕获异常并用 traceback 把它们记录下来。比如下面这个例子:
open('/path/to/does/not/exist', 'rb')
except (SystemExit, KeyboardInterrupt):
except Exception, e:
logger.error('Failed to open file', exc_info=True)
try:&&&&open('/path/to/does/not/exist', 'rb')except (SystemExit, KeyboardInterrupt):&&&&raiseexcept Exception, e:&&&&logger.error('Failed to open file', exc_info=True)
使用参数 exc_info=true 调用 logger 方法, traceback 会输出到 logger 中。你可以看到下面的结果:
ERROR:__main__:Failed to open file
Traceback (most recent call last):
File "example.py", line 6, in &module&
open('/path/to/does/not/exist', 'rb')
IOError: [Errno 2] No such file or directory: '/path/to/does/not/exist'
ERROR:__main__:Failed to open fileTraceback (most recent call last):&&File "example.py", line 6, in &module&&&&&open('/path/to/does/not/exist', 'rb')IOError: [Errno 2] No such file or directory: '/path/to/does/not/exist'
你也可以调用 logger.exception(msg, _args),它等价于 logger.error(msg, exc_info=True, _args)。
千万不要在模块层次获取 Logger,除非 disable_existing_loggers 被设置为 False
你可以看到很多在模块层次获取 logger 的例子(在这篇文章我也使用了很多,但这仅仅为了让示例更短一些)。它们看上去没什么坏处,但事实上,这儿是有陷阱的 – 如果你像这样在模块中使用 Logger,Python 会保留从文件中读入配置前所有创建的所有 logger。
my_module.py
import logging
logger = logging.getLogger(__name__)
def foo():
('Hi, foo')
class Bar(object):
def bar(self):
('Hi, bar')
12345678910
import logging&logger = logging.getLogger(__name__)&def foo():&&&&logger.info('Hi, foo')&class Bar(object):&&&&def bar(self):&&&&&&&&logger.info('Hi, bar')
import logging
logger = logging.getLogger(__name__)
def foo():
('Hi, foo')
class Bar(object):
def bar(self):
('Hi, bar')
12345678910
import logging&logger = logging.getLogger(__name__)&def foo():&&&&logger.info('Hi, foo')&class Bar(object):&&&&def bar(self):&&&&&&&&logger.info('Hi, bar')
logging.ini
[handlers]
keys=consoleHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
12345678910111213141516171819202122
[loggers]keys=root&[handlers]keys=consoleHandler&[formatters]keys=simpleFormatter&[logger_root]level=DEBUGhandlers=consoleHandler&[handler_consoleHandler]class=StreamHandlerlevel=DEBUGformatter=simpleFormatterargs=(sys.stdout,)&[formatter_simpleFormatter]format=%(asctime)s - %(name)s - %(levelname)s - %(message)sdatefmt=
本应该在日志中看到记录,但是你却什么也没有看到。为什么呢?这就是因为你在模块层次创建了 logger,然后你又在加载日志配置文件之前就导入了模块。logging.fileConfig 与 logging.dictConfig 默认情况下会使得已经存在的 logger 失效。所以,这些配置信息不会应用到你的 Logger 上。你最好只在你需要 logger 的时候才获得它。反正创建或者取得 logger 的成本很低。你可以这样写你的代码:
import logging
def foo():
logger = logging.getLogger(__name__)
('Hi, foo')
class Bar(object):
def __init__(self, logger=None):
self.logger = logger or logging.getLogger(__name__)
def bar(self):
('Hi, bar')
123456789101112
import logging&def foo():&&&&logger = logging.getLogger(__name__)&&&&logger.info('Hi, foo')&class Bar(object):&&&&def __init__(self, logger=None):&&&&&&&&self.logger = logger or logging.getLogger(__name__)&&&&&def bar(self):&&&&&&&&self.logger.info('Hi, bar')
这样,logger 就会在你加载配置后才会被创建。这样配置信息就可以正常应用。
python2.7 之后的版本中 fileConfg 与 dictConfig 都新添加了 “disable_existing_loggers” 参数,将其设置为 False,上面提到的问题就可以解决了。例如:
import logging
import logging.config
logger = logging.getLogger(__name__)
# load config from file
# logging.config.fileConfig('logging.ini', disable_existing_loggers=False)
# or, for dictConfig
logging.config.dictConfig({
'version': 1,
'disable_existing_loggers': False,
# this fixes the problem
'formatters': {
'standard': {
'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
'handlers': {
'default': {
'level':'INFO',
'class':'logging.StreamHandler',
'loggers': {
'handlers': ['default'],
'level': 'INFO',
'propagate': True
('It works!')
123456789101112131415161718192021222324252627282930313233343536
import loggingimport logging.config&logger = logging.getLogger(__name__)&# load config from file &# logging.config.fileConfig('logging.ini', disable_existing_loggers=False)&# or, for dictConfig&logging.config.dictConfig({&&&&'version': 1,&&&&&&&&&&&&&&&&&&'disable_existing_loggers': False,&&# this fixes the problem&&&&&'formatters': {&&&&&&&&'standard': {&&&&&&&&&&&&'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'&&&&&&&&},&&&&},&&&&'handlers': {&&&&&&&&'default': {&&&&&&&&&&&&'level':'INFO',&&&&&&&&&&&&&&&&'class':'logging.StreamHandler',&&&&&&&&},&&&&&&},&&&&'loggers': {&&&&&&&&'': {&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'handlers': ['default'],&&&&&&&&&&&&&&&&&&&&'level': 'INFO',&&&&&&&&&&&&&&'propagate': True&&&&&&&&&&}&&&&}})&logger.info('It works!')
使用 JSON 或者 YAML 记录配置
虽然你可以在 python 代码中配置你的日志系统,但是这样并不够灵活。最好的方法是使用一个配置文件来配置。在 Python2.7 及之后的版本中,你可以从字典中加载 logging 配置。这也就意味着你可以从 JSON 或者 YAML 文件中加载日志的配置。尽管你还能用原来 .ini 文件来配置,但是它既很难读也很难写。下面我给你们看一个用 JSON 和 YAML 文件配置的例子:
logging.json
"version": 1,
"disable_existing_loggers": false,
"formatters": {
"simple": {
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"formatter": "simple",
"stream": "ext://sys.stdout"
"info_file_handler": {
"class": "logging.handlers.RotatingFileHandler",
"level": "INFO",
"formatter": "simple",
"filename": "info.log",
"maxBytes": ,
"backupCount": 20,
"encoding": "utf8"
"error_file_handler": {
"class": "logging.handlers.RotatingFileHandler",
"level": "ERROR",
"formatter": "simple",
"filename": "errors.log",
"maxBytes": ,
"backupCount": 20,
"encoding": "utf8"
"loggers": {
"my_module": {
"level": "ERROR",
"handlers": ["console"],
"propagate": "no"
"level": "INFO",
"handlers": ["console", "info_file_handler", "error_file_handler"]
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
{&&&&"version": 1,&&&&"disable_existing_loggers": false,&&&&"formatters": {&&&&&&&&"simple": {&&&&&&&&&&&&"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"&&&&&&&&}&&&&},&&&&&"handlers": {&&&&&&&&"console": {&&&&&&&&&&&&"class": "logging.StreamHandler",&&&&&&&&&&&&"level": "DEBUG",&&&&&&&&&&&&"formatter": "simple",&&&&&&&&&&&&"stream": "ext://sys.stdout"&&&&&&&&},&&&&&&&&&"info_file_handler": {&&&&&&&&&&&&"class": "logging.handlers.RotatingFileHandler",&&&&&&&&&&&&"level": "INFO",&&&&&&&&&&&&"formatter": "simple",&&&&&&&&&&&&"filename": "info.log",&&&&&&&&&&&&"maxBytes": ,&&&&&&&&&&&&"backupCount": 20,&&&&&&&&&&&&"encoding": "utf8"&&&&&&&&},&&&&&&&&&"error_file_handler": {&&&&&&&&&&&&"class": "logging.handlers.RotatingFileHandler",&&&&&&&&&&&&"level": "ERROR",&&&&&&&&&&&&"formatter": "simple",&&&&&&&&&&&&"filename": "errors.log",&&&&&&&&&&&&"maxBytes": ,&&&&&&&&&&&&"backupCount": 20,&&&&&&&&&&&&"encoding": "utf8"&&&&&&&&}&&&&},&&&&&"loggers": {&&&&&&&&"my_module": {&&&&&&&&&&&&"level": "ERROR",&&&&&&&&&&&&"handlers": ["console"],&&&&&&&&&&&&"propagate": "no"&&&&&&&&}&&&&},&&&&&"root": {&&&&&&&&"level": "INFO",&&&&&&&&"handlers": ["console", "info_file_handler", "error_file_handler"]&&&&}}
logging.yaml
version: 1
disable_existing_loggers: False
formatters:
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
class: logging.StreamHandler
level: DEBUG
formatter: simple
stream: ext://sys.stdout
info_file_handler:
class: logging.handlers.RotatingFileHandler
level: INFO
formatter: simple
filename: info.log
backupCount: 20
encoding: utf8
error_file_handler:
class: logging.handlers.RotatingFileHandler
level: ERROR
formatter: simple
filename: errors.log
backupCount: 20
encoding: utf8
my_module:
level: ERROR
handlers: [console]
propagate: no
level: INFO
handlers: [console, info_file_handler, error_file_handler]
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
---&version: 1&disable_existing_loggers: False&formatters:&&&&&simple:&&&&&&&&&format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"&handlers:&&&&&console:&&&&&&&&&class: logging.StreamHandler&&&&&&&&&level: DEBUG&&&&&&&&&formatter: simple&&&&&&&&&stream: ext://sys.stdout&&&&&info_file_handler:&&&&&&&&&class: logging.handlers.RotatingFileHandler&&&&&&&&&level: INFO&&&&&&&&&&&&&&&&&&&&&formatter: simple&&&&&&&&&filename: info.log&&&&&&&&&maxBytes:
# 10MB&&&&&&&&&backupCount: 20&&&&&&&&&encoding: utf8&&&&&error_file_handler:&&&&&&&&&class: logging.handlers.RotatingFileHandler&&&&&&&&&level: ERROR&&&&&&&&&&&&&&&&&&&&&formatter: simple&&&&&&&&&filename: errors.log&&&&&&&&&maxBytes:
# 10MB&&&&&&&&&backupCount: 20&&&&&&&&&encoding: utf8&loggers:&&&&&my_module:&&&&&&&&&level: ERROR&&&&&&&&&handlers: [console]&&&&&&&&&propagate: no&root:&&&&&level: INFO&&&&&handlers: [console, info_file_handler, error_file_handler]&...
接下来将展示怎样从 JSON 文件中读入日志的配置信息:
import json
import logging.config
def setup_logging(
default_path='logging.json',
env_key='LOG_CFG'
"""Setup logging configuration
path = default_path
value = os.getenv(env_key, None)
path = value
if os.path.exists(path):
with open(path, 'rt') as f:
config = json.load(f)
logging.config.dictConfig(config)
logging.basicConfig(level=default_level)
123456789101112131415161718192021
import jsonimport logging.config&def setup_logging(&&&&default_path='logging.json', &&&&default_level=logging.INFO,&&&&env_key='LOG_CFG'):&&&&"""Setup logging configuration&&&&&"""&&&&path = default_path&&&&value = os.getenv(env_key, None)&&&&if value:&&&&&&&&path = value&&&&if os.path.exists(path):&&&&&&&&with open(path, 'rt') as f:&&&&&&&&&&&&config = json.load(f)&&&&&&&&logging.config.dictConfig(config)&&&&else:&&&&&&&&logging.basicConfig(level=default_level)
使用 JSON 的一个优点就是 json是一个标准库,你不需要额外安装它。但是从我个人来说,我比较喜欢 YAML 一些。它无论是读起来还是写起来都比较容易。你也可以使用下面的方法来加载一个 YAML 配置文件:
import logging.config
import yaml
def setup_logging(
default_path='logging.yaml',
env_key='LOG_CFG'
"""Setup logging configuration
path = default_path
value = os.getenv(env_key, None)
path = value
if os.path.exists(path):
with open(path, 'rt') as f:
config = yaml.load(f.read())
logging.config.dictConfig(config)
1234567891011121314151617181920212223
import osimport logging.config&import yaml&def setup_logging(&&&&default_path='logging.yaml', &&&&default_level=logging.INFO,&&&&env_key='LOG_CFG'):&&&&"""Setup logging configuration&&&&&"""&&&&path = default_path&&&&value = os.getenv(env_key, None)&&&&if value:&&&&&&&&path = value&&&&if os.path.exists(path):&&&&&&&&with open(path, 'rt') as f:&&&&&&&&&&&&config = yaml.load(f.read())&&&&&&&&logging.config.dictConfig(config)&&&&else:&&&&&&&&lo
接下来,你就可以在运行程序的时候调用 setup_logging 来启动日志记录了。它默认会读取 logging.json 或 logging.yaml 文件 。你也可以设置环境变量 LOG_CCFG 从指定路径加载日志配置。例如:
LOG_CFG=my_logging.json python my_server.py
LOG_CFG=my_logging.json python my_server.py
如果你喜欢 YAML:
LOG_CFG=my_logging.yaml python my_server.py
LOG_CFG=my_logging.yaml python my_server.py
使用旋转文件句柄
如果你用 FileHandler 写日志,文件的大小会随着时间推移而不断增大。最终有一天它会占满你所有的磁盘空间。为了避免这种情况出现,你可以在你的生成环境中使用 RotatingFileHandler 替代 FileHandler。
如果你有多个服务器可以启用一个专用的日志服务器
当你有多个服务器和不同的日志文件时,你可以创建一个集中式的日志系统来收集重要的(大多数情况是警告或者错误消息)信息。然后通过监测这些日志信息,你就可以很容易地发现系统中的问题了。
Python 的日志库设计得如此之好,真是让人欣慰,我觉得这是标准库中最好的一部分了,你不得不选择它。它很灵活,你可以用你自己的 handler 或者 filter。已经有很多的第三方的 handler 了,比如 pyzmq 提供的 ZeroMQ 日志句柄,它允许你通过 zmq 套接字发送日志消息。如果你还不知道怎么正确的使用日志系统,这篇文章将会非常有用。有了很好的日志记录实践,你就能非常容易地发现系统中的问题。这是很非常值得投资的。:)
关于作者:
可能感兴趣的话题
以合适的等级输出日志记录,这个部分,有拼写错误,CRITICAL拼写成了CRITIAL ,漏了个 A,除此之外,文章写的很好,正在学习日志模块,很有用,翻译的也很易懂
o 239 回复
关于 Python 频道
Python频道分享 Python 开发技术、相关的行业动态。
新浪微博:
推荐微信号
(加好友请注明来意)
– 好的话题、有启发的回复、值得信赖的圈子
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选文章
– UI,网页,交互和用户体验
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
& 2017 伯乐在线}

我要回帖

更多关于 黑马程序员python视频 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信