
要把代码发现来才知道,以下是常见的错误
下面终于要讲到当你用到更多的Python的功能(数据类型,函数,模块,类等等)时可能碰到的问题了。由于篇幅有限,这里尽量精简,尤其是对一些高级的概念。要想了解更多的细节,敬请阅读Learning Python, 2nd Edition的“小贴士”以及“Gotchas”章节。
打开文件的调用不使用模块搜索路径
当你在Python中调用open()来访问一个外部的文件时,Python不会使用模块搜索路径来定位这个目标文件。它会使用你提供的绝对路径,或者假定这个文件是在当前工作目录中。模块搜索路径仅仅为模块加载服务的。
不同的类型对应的方法也不同
列表的方法是不能用在字符串上的,反之亦然。通常情况下,方法的调用是和数据类型有关的,但是内部函数通常在很多类型上都可以使用。举个例子来说,列表的reverse方法仅仅对列表有用,但是len函数对任何具有长度的对象都适用
不能直接改变不可变数据类型
记住你没法直接的改变一个不可变的对象(例如,元组,字符串):
T = (1, 2, 3)
T[2] = 4 # 错误
用切片,联接等构建一个新的对象,并根据需求将原来变量的值赋给它。因为Python会自动回收没有用的内存,因此这没有看起来那么浪费:
T = T[:2] + (4,) # 没问题了: T 变成了 (1, 2, 4)
使用简单的for循环而不是while或者range
当你要从左到右遍历一个有序的对象的所有元素时,用简单的for循环(例如,for x in seq:)相比于基于while-或者range-的计数循环而言会更容易写,通常运行起来也更快。除非你一定需要,尽量避免在一个for循环里使用range:让Python来替你解决标号的问题。在下面的例子中三个循环结构都没有问题,但是第一个通常来说更好;在Python里,简单至上。
S = "lumberjack"
for c in S: print c # 最简单
for i in range(len(S)): print S[i] # 太多了
i = 0 # 太多了
while i < len(S): print S[i]; i += 1
不要试图从那些会改变对象的函数得到结果
诸如像方法listappend()和listsort()一类的直接改变 *** 作会改变一个对象,但不会将它们改变的对象返回出来(它们会返回None);正确的做法是直接调用它们而不要将结果赋值。经常会看见初学者会写诸如此类的代码:
mylist = mylistappend(X)
目的是要得到append的结果,但是事实上这样做会将None赋值给mylist,而不是改变后的列表。更加特别的一个例子是想通过用排序后的键值来遍历一个字典里的各个元素,请看下面的例子:
D = {}
for k in Dkeys()sort(): print D[k]
差一点儿就成功了——keys方法会创建一个keys的列表,然后用sort方法来将这个列表排序——但是因为sort方法会返回None,这个循环会失败,因为它实际上是要遍历None(这可不是一个序列)。要改正这段代码,将方法的调用分离出来,放在不同的语句中,如下:
Ks = Dkeys()
Kssort()
for k in Ks: print D[k]
只有在数字类型中才存在类型转换
在Python中,一个诸如123+3145的表达式是可以工作的——它会自动将整数型转换为浮点型,然后用浮点运算。但是下面的代码就会出错了:
S = "42"
I = 1
X = S + I # 类型错误
这同样也是有意而为的,因为这是不明确的:究竟是将字符串转换为数字(进行相加)呢,还是将数字转换为字符串(进行联接)呢?在Python中,我们认为“明确比含糊好”(即,EIBTI(Explicit is better than implicit)),因此你得手动转换类型:
X = int(S) + I # 做加法: 43
X = S + str(I) # 字符串联接: "421"
循环的数据结构会导致循环
尽管这在实际情况中很少见,但是如果一个对象的集合包含了到它自己的引用,这被称为循环对象(cyclic object)。如果在一个对象中发现一个循环,Python会输出一个[…],以避免在无限循环中卡住:
>>> L = ['grail'] # 在 L中又引用L自身会
>>> Lappend(L) # 在对象中创造一个循环
>>> L
['grail', []]
除了知道这三个点在对象中表示循环以外,这个例子也是很值得借鉴的。因为你可能无意间在你的代码中出现这样的循环的结构而导致你的代码出错。如果有必要的话,维护一个列表或者字典来表示已经访问过的对象,然后通过检查它来确认你是否碰到了循环。
赋值语句不会创建对象的副本,仅仅创建引用
这是Python的一个核心理念,有时候当行为不对时会带来错误。在下面的例子中,一个列表对象被赋给了名为L的变量,然后L又在列表M中被引用。内部改变L的话,同时也会改变M所引用的对象,因为它们俩都指向同一个对象。
>>> L = [1, 2, 3] # 共用的列表对象
>>> M = ['X', L, 'Y'] # 嵌入一个到L的引用
>>> M
['X', [1, 2, 3], 'Y']
>>> L[1] = 0 # 也改变了M
>>> M
['X', [1, 0, 3], 'Y']
通常情况下只有在稍大一点的程序里这就显得很重要了,而且这些共用的引用通常确实是你需要的。如果不是的话,你可以明确的给他们创建一个副本来避免共用的引用;对于列表来说,你可以通过使用一个空列表的切片来创建一个顶层的副本:
>>> L = [1, 2, 3]
>>> M = ['X', L[:], 'Y'] # 嵌入一个L的副本
>>> L[1] = 0 # 仅仅改变了L,但是不影响M
>>> L
[1, 0, 3]
>>> M
['X', [1, 2, 3], 'Y']
切片的范围起始从默认的0到被切片的序列的最大长度。如果两者都省略掉了,那么切片会抽取该序列中的所有元素,并创造一个顶层的副本(一个新的,不被公用的对象)。对于字典来说,使用字典的dictcopy()方法。
静态识别本地域的变量名
Python默认将一个函数中赋值的变量名视作是本地域的,它们存在于该函数的作用域中并且仅仅在函数运行的时候才存在。从技术上讲,Python是在编译def代码时,去静态的识别本地变量,而不是在运行时碰到赋值的时候才识别到的。如果不理解这点的话,会引起人们的误解。比如,看看下面的例子,当你在一个引用之后给一个变量赋值会怎么样:
>>> X = 99
>>> def func():
print X # 这个时候还不存在
X = 88 # 在整个def中将X视作本地变量
>>> func( ) # 出错了!
你会得到一个“未定义变量名”的错误,但是其原因是很微妙的。当编译这则代码时,Python碰到给X赋值的语句时认为在这个函数中的任何地方X会被视作一个本地变量名。但是之后当真正运行这个函数时,执行print语句的时候,赋值语句还没有发生,这样Python便会报告一个“未定义变量名”的错误。
事实上,之前的这个例子想要做的事情是很模糊的:你是想要先输出那个全局的X,然后创建一个本地的X呢,还是说这是个程序的错误?如果你真的是想要输出这个全局的X,你需要将它在一个全局语句中声明它,或者通过包络模块的名字来引用它。
默认参数和可变对象
在执行def语句时,默认参数的值只被解析并保存一次,而不是每次在调用函数的时候。这通常是你想要的那样,但是因为默认值需要在每次调用时都保持同样对象,你在试图改变可变的默认值(mutable defaults)的时候可要小心了。例如,下面的函数中使用一个空的列表作为默认值,然后在之后每一次函数调用的时候改变它的值:
>>> def saver(x=[]): # 保存一个列表对象
xappend(1) # 并每次调用的时候
print x # 改变它的值
>>> saver([2]) # 未使用默认值
[2, 1]
>>> saver() # 使用默认值
[1]
>>> saver() # 每次调用都会增加!
[1, 1]
>>> saver()
[1, 1, 1]
有的人将这个视作Python的一个特点——因为可变的默认参数在每次函数调用时保持了它们的状态,它们能提供像C语言中静态本地函数变量的类似的一些功能。但是,当你第一次碰到它时会觉得这很奇怪,并且在Python中有更加简单的办法来在不同的调用之间保存状态(比如说类)。
要摆脱这样的行为,在函数开始的地方用切片或者方法来创建默认参数的副本,或者将默认值的表达式移到函数里面;只要每次函数调用时这些值在函数里,就会每次都得到一个新的对象:
>>> def saver(x=None):
if x is None: x = [] # 没有传入参数?
xappend(1) # 改变新的列表
print x
>>> saver([2]) # 没有使用默认值
[2, 1]
>>> saver() # 这次不会变了
[1]
>>> saver()
[1]
其他常见的编程陷阱
下面列举了其他的一些在这里没法详述的陷阱:
在顶层文件中语句的顺序是有讲究的:因为运行或者加载一个文件会从上到下运行它的语句,所以请确保将你未嵌套的函数调用或者类的调用放在函数或者类的定义之后。
reload不影响用from加载的名字:reload最好和import语句一起使用。如果你使用from语句,记得在reload之后重新运行一遍from,否则你仍然使用之前老的名字。
在多重继承中混合的顺序是有讲究的:这是因为对superclass的搜索是从左到右的,在类定义的头部,在多重superclass中如果出现重复的名字,则以最左边的类名为准。
在try语句中空的except子句可能会比你预想的捕捉到更多的错误。在try语句中空的except子句表示捕捉所有的错误,即便是真正的程序错误,和sysexit()调用,也会被捕捉到。
cat,将内容一次性展现。18G的文件,估计展现后滚屏都得滚动几分钟,你只能看到最后一屏;
less,将内容分屏展现。用空格或pagedown翻页,用pageup回滚到上一屏;
more,类似less,但只能向下翻屏,不能向上,看过的就没法再回滚。
grep,过滤关键字,查询你关心的包含关键字的行,可配合管道符加more或less
你还可以用上述命令加管道符加上sed命令获取更详细的内容。
我们可以利用 docker logs 命令查看 Docker 容器内部应用程序运行时所产生的日志,可以免除首先进入 Docker 容器,再打开应用程序的日志文件的过程。docker logs 会监控容器中 *** 作系统的标准输出设备(STDOUT),一旦 STDOUT 有数据产生,就会将这些数据传输到另一个“设备”中,该 Docker 的被称为“日志驱动(Logging Driver)”
例如,我们有一个容器实例 ID 为 “da6743d61e1a” ,随后我们使用 docker logs 命令,查看 da6743d61e1a 容器的日志
此时,Docker 日志也在同步输出,输出的日志类似下面这样。
Docker 是怎样做到的呢?或者说,所谓的 Docker 日志驱动,到底做了些什么事情?
我们使用 docker info 命令,可以看到 Docker 容器的相关信息,其中有一项 Logging Driver 的字段。
通过输入以上命令,将得到Docker 当前所设置的日志驱动类型:journald
其实,Docker 已为我们提供了大量的日志驱动类型。
通过 --log-opt 参数为 json-file 日志驱动添加了两个选项,max-size=10m 表示 JSON 文件最大为 10MB(超过 10MB 就会自动生成新文件),max-file=3 表示 JSON 文件最多为3个(超过3个就会自动删除多余的旧文件)
除了在启动 Docker 容器时,可指定日志驱动以外,还可以通过修改 Docker 配置文件来指定日志驱动。
打开配置文件 /etc/sysconfig/docker ,找到以下配置片段:
可以看出,默认的日志驱动为 journald,把它修改为 syslog
然后重启 docker
以上众多日志驱动类型中,较为常用 的是 Syslog,因为 Syslog 是 Linux 的日志系统,很多日志分析工具都可以从 Syslog 中获取日志,比如流行的 ELK(Elasticsearch、Logstash、Kibana)日志中心。Logstash 用于收集日志,Syslog 中写入的日志可转发到 Logstash 中,随后将日志存入 Elasticsearch 中,最后可通过 Kibana 来查询日志。
接下来咱们的目标是将 Docker 容器中输出的日志写入 Syslog,那么后面需要做的就是将 Syslog 接入 ELK 了。
默认,Linux *** 作系统已经安装了 Syslog 软件包,但它叫 Rsyslog。实际上,Rsyslog 是 Syslog 标准的一种实现,还有一种叫 Syslog-ng 的第三方实现。虽然 Syslog-ng 的功能较为强大,但我们还是选择使用 Rsyslog,因为 *** 作系统已经预装了,我们无须单独安装,可以通过以下命令查看 Rsyslog 是否已安装。
如果要开启 Rsyslog 服务,我们必须对 Rsyslog 进行配置,打开文件 vi /etc/rsyslogconf
在 rsyslogconf 文件中有一段配置,我们需要手工去开启
重启 Rsyslog 服务,否则配置无法生效
此时,我们可以查看本地是否对外开启了 514 端口
122 syslog日志
syslog是一个被UNIX和Linux广泛使用的日志系统,Linux系统中大部分的日志文件都是通过它进行管理的。本节将对syslog的功能及配置、日志文件的查看和管理,以及syslog中默认配置的日志文件进行介绍。
1221 syslog简介
syslog是一个历史悠久的日志系统,几乎所有的UNIX和Linux *** 作系统都是采用syslog进行系统日志的管理和配置。Linux系统内核和许多程序会产生各种错误信息、警告信息和其他的提示信息。这些信息对管理员了解系统的运行状态是非常有用的,所以应该把它们写到日志文件中去。而执行这个过程的程序就是syslog。syslog可以根据信息的来源以及信息的重要程度将信息保存到不同的日志文件中,例如,为了方便查阅,可以把内核信息与其他信息分开,单独保存到一个独立的日志文件中。在默认的syslog配置下,日志文件通常都保存在“/var/log”目录下。syslog的守护进程为syslogd,系统启动时,默认会自动运行syslogd守护进程,如图125所示。
1如下图所示,先cd到我们需要监控的日志目录。
2这里我们先使用cat命令查看下日志信息,方便与动态监控进行对比。
3下面先讲解下tail命令实现查看最后一部分日志的方法。tail 文件名,默认显示最后10行。
4接着我们把10行的默认值改成显示20行。tail -n 20 文件名
5通过上面的铺垫,我们来看看如何动态监控日志尾部,那就是使用命令:tail -f 文件名,可以从下图看出查看日志后并没有退出,一直在等待刷新日志尾部信息。
6最后,设置下我们要监控的尾部行数。
扩展资料:
Linux完全兼容POSIX10标准
这使得可以在Linux下通过相应的模拟器运行常见的DOS、Windows的程序。这为用户从Windows转到Linux奠定了基础。许多用户在考虑使用Linux时,就想到以前在Windows下常见的程序是否能正常运行,这一点就消除了他们的疑虑。
Linux支持多种平台
Linux可以运行在多种硬件平台上,如具有x86、680x0、SPARC、Alpha等处理器的平台。此外Linux还是一种嵌入式 *** 作系统,可以运行在掌上电脑、机顶盒或游戏机上。2001年1月份发布的Linux 24版内核已经能够完全支持Intel 64位芯片架构。同时Linux也支持多处理器技术。多个处理器同时工作,使系统性能大大提高。
参考资料来源:百度百科:Linux
日志的概念为了维护自身系统资源的运行状况,计算机系统一般都会有相应的日志记录系统有关日常事件或者误 *** 作警报的日期及时间戳信息。这些日志信息对计算机犯罪调查人员非常有用。所谓日志(Log)是指系统所指定对象的某些 *** 作和其 *** 作结果按时间有序的集合。每个日志文件由日志记录组成,每条日志记录描述了一次单独的系统事件。通常情况下,系统日志是用户可以直接阅读的文本文件,其中包含了一个时间戳和一个信息或者子系统所特有的其他信息。日志文件为服务器、工作站、防火墙和应用软件等IT资源相关活动记录必要的、有价值的信息,这对系统监控、查询、报表和安全审计是十分重要的。日志文件中的记录可提供以下用途:监控系统资源;审计用户行为;对可疑行为进行告警;确定入侵行为的范围;为恢复系统提供帮助;生成调查报告;为打击计算机犯罪提供证据来源。日志的特点日志记录着系统中特定事件的相关活动信息,从计算机取证角度看,日志主要有以下特点:(1)不易读懂虽然大部分系统的日志都以文本的形式记录,但由于各系统日志格式不一致,不熟悉各类日志格式就很难获取有用的信息。同时有相当部分应用系统并不采用文本格式记录着日志信息,必须借助专用的工具分析这些日志,否则很难读懂其中的日志信息。(2)数据量大通常对外服务产生的日志文件如Web服务日志、防火墙、入侵检测系统日志和数据库日志以及各类服务器日志等都很大,一个日志文件一天产生的容量少则几十兆、几百兆,多则有几个G,几十个G,这使得获取和分析日志信息变得很困难。(3)不易获取由于网络中不同的 *** 作系统、应用软件、网络设备和服务产生不同的日志文件,即使相同的服务如IIS也可采用不同格式的日志文件记录日志信息。目前国际上还没有形成标准的日志格式,各系统开发商和网络设备生产商往往根据各自的需要制定自己的日志格式,使得不同系统的日志格式和存储方式有所差别。如何获取各类不同系统产生的不同日志文件作为打击计算机犯罪者的电子证据变得尤为困难。(4)不同日志之间存在某种必然的联系一个系统的日志是对本系统涉及的运行状况的信息按时间顺序作一简单的记录,仅反映本系统的某些特定事件的 *** 作情况,并不完全反映某一用户的整个活动情况。一个用户在网络活动的过程中会在很多的系统日志中留下痕迹,如防火墙IDS日志、 *** 作系统日志等,这些不同的日志之间存在某种必然的联系来反映用户的活动情况。只有将多个系统的日志结合起来分析,才能准确反映用户活动情况。(5)容易被修改、破坏甚至伪造产生系统日志的软件通常为应用系统而不是作为 *** 作系统的子系统运行,所产生的日志记录容易遭到恶意的破坏或修改。系统日志通常存储在系统未经保护的目录中,并以文本方式存储,未经加密和校验处理,没有提供防止恶意篡改的有效保护机制。因此,日志文件并不一定是可靠的,入侵者可能会篡改日志文件,从而不能被视为有效的证据。由于日志是直接反映入侵者痕迹的,在计算机取证中扮演着重要的角色,入侵者获取系统权限窃取机密信息或破坏重要数据后往往会修改或删除与其相关的日志信息,甚至根据系统的漏洞伪造日志以迷惑系统管理员和审计。 Unix系统日志在Unix下,最常用的存放日志文件的目录是: /usr/adm 早期版本的 Unix /var/adm 较新版本的 Unix /var/log 用于Solaris,Linux,BSD等 /etc Unix system V早期版本 在这些目录下,或其子目录下,你可以找到以下日志文件(也许是其中的一部分): lastlog 记录用户最后一次成功登录时间 loginlog 不良的登陆尝试记录 messages 记录输出到系统主控台以及由syslog系统服务程序产生的消息 utmp 记录当前登录的每个用户 utmpx 扩展的utmp wtmp 记录每一次用户登录和注销的历史信息 wtmpx 扩展的wtmp voldlog 记录使用外部介质出现的错误 xferkig 记录Ftp的存取情况 sulog 记录su命令的使用情况 acct 记录每个用户使用过的命令 aculog 拨出自动呼叫记录 记录输出到系统主控台以及由syslog系统服务程序产生的消息。syslog采用可配置的、统一的系统登记程序,随时从系统各处接受log请求,然后根据/etc/syslogconf中的预先设定把log信息写入相应文件中、邮寄给特定用户或者直接以消息的方式发往控制台。值得注意的是,为了防止入侵者修改、删除messages里的记录信息,可以采用用打印机记录或跨越网络登记的方式来挫败入侵者的企图。任何程序都可以通过syslog记录事件。Syslog可以记录系统事件,可以写到一个文件或设备中,或给用户发送一个信息。它能记录本地事件或通过网络记录到另一台主机上的事件。 Syslog依据两个重要的文件:/sbin/syslogd(守护进程)和/etc/syslogconf配置文件。习惯上,多数syslog信息被写到/var/adm或/ar/log目录下的信息文件中(message)。一个典型的syslog记录包括生成程序的名字和一个文本信息,它还包括一个设备和一个行为级别(但不在日志中出现)。 Windows系统日志以Windows2000/XP为例,日志文件通常有应用程序日志,安全日志、系统日志、DNS服务器日志、FTP日志、>
1、向控制台输出信息可以使用c语言函数库中的printf(),直接打印出信息,比如:
printf("hello world\n");
2、要将控制台输出的信息保存,则可以在控制台中使用>或者>>将输出信息输出到文件或者追加到文件,>和>>的区别在于>会覆盖原来的文件,而>>会在文件末尾添加。以hello wrold为例:
#include <stdioh>
int main()
{
printf("hello world\n");
return 0;
}
生成程序后,进入程序所在的目录,如下图所示:
以上就是关于python出错,请问是什么问题全部的内容,包括:python出错,请问是什么问题、linux下的一个超大日志文件有18G,用什么工具能打开查看里面的内容呀、将日志输出到Docker容器外等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)