纪录自己在写脚本过程中遇到的一些错误,方便后续查看。
1、文件名与模块中的函数名相同导致
import multiprocessing
import os,time
def inputQ(queue):
info = str(os.getpid()) + '(put):' + str(time.time())
queue.put(info)
def outputQ(queue,lock):
if not queue.empty():
info = queue.get()
lock.acquire()
print((str(os.getpid()) + '(get):' + info))
lock.release()
if __name__ == '__main__':
record1 = []
record2 = []
lock = multiprocessing.Lock()
queue = multiprocessing.Queue()
for i in range(10):
process = multiprocessing.Process(target=inputQ,args=(queue,))
process.start()
record1.append(process)
for i in range(10):
process = multiprocessing.Process(target=outputQ,args=(queue,lock))
process.start()
record2.append(process)
for p in record1:
p.join()
queue.close()
for p in record2:
p.join()
运行后错误提示如下:
from queue import Empty, Full
ImportError: cannot import name 'Empty'
这个问题比较隐蔽,提示from queue import Empty, Full,还专门看了源码,以为没有empty和full两个类,结果看了以后是有的,并且代码在python2.7的环境下可以正常运行,我目前使用的是python3.5版本,报这个错误,一度怀疑是不是python3和python2的区别导致的这个错误,最后尝试把代码文件名queue.py改成了queue01.py才解决该问题,所以文件命名时一定要注意。。。
2、变量名与函数名相同导致
使用ipython调试脚本时,一直报如下错误,代码很简单,最后发现之前调试时,有变量名字为str,与string模块中的str函数重名,所以报如下错误,所以再给变量命名时,应注意。
>>> random_gen_cid()
Traceback (most recent call last):
File "" , line 1, in
File "" , line 2, in random_gen_cid
TypeError: 'str' object is not callable
3、未安装相应的模块
在使用configobj 模块时,提示:
>>> from configobj import ConfigObj
Traceback (most recent call last):
File "" , line 1, in <module>
ImportError: No module named configobj
由于没有安装configobj 模块,在终端使用pip install configobj安装即可。
4、KeyError报错
提示如下:
Traceback (most recent call last):
File "" , line 3, in <module>
File "C:\Python27\lib\site-packages\configobj.py", line 554, in __getitem__
val = dict.__getitem__(self, key)
KeyError: 'read_interface'
字典中没有关键字’read_interface’,我在代码中使用了config1 = ConfigObj(tel_conf)
,打印config1 ,发现config1为空的元祖,检查发现,tel_conf的路径写错了,导致为空,config1中无关键字’read_interface’。
5、缩进异常
错误提示:
>>> dict = {'Name': 'Zara', 'Age': 7};
File "" , line 1
dict = {'Name': 'Zara', 'Age': 7};
^
IndentationError: unexpected indent
提示缩进异常,调整缩进即可。
>>> dict = {'Name': 'Zara', 'Age': 7};
>>>
6、导入模块错误
>>> from common import *
Traceback (most recent call last):
File "" , line 1, in
File ".\common.py", line 11
SyntaxError: Non-ASCII character '\xe9' in file .\common.py on line 11, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
>>>
一直以为python模块中有个模块common,还尝试安装common模块,结果安装不成功,百度结果都是说需要设置字符编码#coding=utf-8,但是不起作用,真是对自己无语了,当前目录下,有同事写的common.py文件,from common import *,就是直接导入了当前目录下的common模块,因为调试的时候,用的ipython调试,直接执行from common import *
,所以导致上述错误。
需明白,导入模块时,python首先查找当前目录下的模块。
7、用ipython调试时,比如很简单的一段代码:
>>> s = 0
>>> for i in range(11):
... s = s + i
... print s
File "" , line 3
print s
^
SyntaxError: invalid syntax
一直提示语法错误SyntaxError: invalid syntax,搞了好久,才发现ipython调试代码时,循环语句写完以后,要多敲一个回车,退出循环,才能接着写下面的语句;修改后正常。
8、递归函数栈溢出
>>> def func(n):
... if n==1:
... return 1
... else:
... return n*func(n-1)
...
>>> func(100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000L
>>> func(1000)
Traceback (most recent call last):
File "" , line 1, in
File "" , line 5, in func
.
.
.
File "" , line 5, in func
RuntimeError: maximum recursion depth exceeded
使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。
解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。
尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。
上面的fact(n)函数由于return n * fact(n - 1)引入了乘法表达式,所以就不是尾递归了。要改成尾递归方式,需要多一点代码,主要是要把每一步的乘积传入到递归函数中:
>>> def fact_iter(num, product):
if num == 1:
return product
return fact_iter(num - 1, num * product)
... ... ... ...
>>> def fact(n):
return fact_iter(n, 1)
... ... >>>
>>> fact(5)
120
>>> fact(1000)
Traceback (most recent call last):
File "" , line 1, in
File "" , line 2, in fact
File "" , line 4, in fact_iter
RuntimeError: maximum recursion depth exceeded
可以看到,return fact_iter(num - 1, num * product)
仅返回递归函数本身,num - 1
和num * product
在函数调用前就会被计算,不影响函数调用。
尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。
遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。
Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。
9、
报错信息:IndentationError: expected an indented block
"base.py" 52L, 1451C written
[root@test30s4 library]# ./base.py
File "./base.py", line 53
^
IndentationError: expected an indented block
很奇怪,我的base.py文件总共才49行,查看base.py文件,发现if __name__ == '__main__':
中,刚才把左右的都给注释了,如下:
if __name__ == '__main__':
#remote_rpc("http://xxxxx.com")
#remote_rpc("http://xxxxx.com")
任意去掉一个#即可。
10、IndentationError: unindent does not match any outer indentation level
File "mysql_opera.py", line 26
def getValue(self,data):
^
IndentationError: unindent does not match any outer indentation level
查看了26行,并没有错误,该行就是定义了一个函数,使用的vim编译器,有时候用的table键空格,有时候用的空格键,于是将所有的缩进全部替换成tab键,重新运行脚本ok!
11、UnboundLocalError: local variable ‘data’ referenced before assignment
(1054, "Unknown column '7nJKEFX9' in 'where clause'")
Traceback (most recent call last):
File "StreamManager.py", line 43, in
test.assertCreateStream()
File "StreamManager.py", line 25, in assertCreateStream
data1 = self.mysql.executeMysql(sql1)
File "/usr/local/sandai/zhang_tools/xcloud_tool/auto_test/stream_Manager_auto/library/mysql_opera.py", line 24, in executeMysql
return data
UnboundLocalError: local variable 'data' referenced before assignment
出问题代码:
cur = conn.cursor()
print("connect success!")
try:
cur.execute(sql)
data = cur.fetchone()
print("select data:", data)
except Exception, e:
print e
cur.close()
conn.commit()
conn.close()
return data
data的范围在try函数中,导致提示此错误,修改代码为:
cur = conn.cursor()
print("connect success!")
try:
cur.execute(sql)
data = cur.fetchone()
print("select data:", data)
cur.close()
conn.commit()
conn.close()
return data
except Exception, e:
print e
即可。
12:SyntaxError: non-default argument follows default argument
# python basic_stream_opera.py
File "basic_stream_opera.py", line 24
def createStream(self, businessID, streamKey, streamName='autotest', streamType='rtmp', pullUrl):
SyntaxError: non-default argument follows default argument
如果一个函数的参数中含有默认参数,则这个默认参数后的所有参数都必须是默认参数 ,
否则会抛出:SyntaxError: non-default argument follows default argument的异常,将此处pullurl添加一个默认参数即可!