工作中, 有一服务需要从freeBSD迁移到centOS上。其中有一python脚本有些鬼异。
在freeBSD上可以正常, 在centOS上不能正常。最后目标定位在脚本最后的代码上, 大概如下:
try:
if 测试条件:
do_someting()
sys.exit(0)
else:
sys.exit(1)
except Exception:
sys.exit(1)
centOS上, python的版本是2.4的。 freeBSD下安装的是2.5.
旧版本的Exception是基类: 因此在2.4上脚本永远是返回1的。
到了新的版本BaseException才是基类: 因此SystemExit和Exception是同一级。脚本可以返回0
这是迁移后的主要问题。 其实, 应该是作者不知道sys.exit的后果。作者把sys.exit当成os._exit了。
如下是APUE里的一幅图:
标准C里的exit函数在调用后, 不是马上退出程序, 而是运行一些收尾工作。比如把buffer里的数据flush到磁盘等等工作。然后才是调用真正的退出函数:_exit
python的sys.exit是抛出一个异常:SystemExit, python会默认会catch这个异常, 大意为:
try:
我们的python代码
exception SystemExit:
做一些收尾工作, 如flush之类的
Sunday, August 15, 2010
递归, 循环, 迭代
工作中, 需要有历遍目录进行一些操作. python自带的os.walk很强大, 但是没有maxdepth这种层数参数.
os.walk是原本是一个递归. 下面是它的代码:
273 try:
274 # Note that listdir and error are globals in this module due
275 # to earlier import-*.
276 names = listdir(top)
277 except error, err:
278 if onerror is not None:
279 onerror(err)
280 return
281
282 dirs, nondirs = [], []
283 for name in names:
284 if isdir(join(top, name)):
285 dirs.append(name)
286 else:
287 nondirs.append(name)
288
289 if topdown:
290 yield top, dirs, nondirs
291 for name in dirs:
292 path = join(top, name)
293 if followlinks or not islink(path):
294 for x in walk(path, topdown, onerror, followlinks):
295 yield x
296 if not topdown:
297 yield top, dirs, nondirs
BTW:: 这里需要注意*nux的ENAMETOOLONG 错误.
递归无法按"层"历遍目录. 它只能一条一条路径走尽.
朋友说使用循环也可以实现递归, 这种代码从来没有写过. 也一直在迷惑。
但是受 http://www.devshed.com/c/a/Python/Basic-Threading-in-Python/2/ 的启发.
突然明白循环是怎么做到递归的。 于是自己使用循环自己写了一个历遍的函数:
def loop_walk(top, n):
stack = Queue.Queue()
sub_stack = Queue.Queue()
dirs = []
files = []
error = None
stack.put([top])
while True:
if stack.empty():
# stack被取完了, 下一层队列
stack, sub_stack = sub_stack, stack
if n <= 1:
yield [], [], None
return
else:
n -= 1
continue
else:
try:
top_list = stack.get(False)
except Queue.Empty:
yield [], [], None
return
for top in top_list:
try:
for item in os.listdir(top):
item = os.path.join(top, item)
if os.path.isdir(item):
dirs.append(item)
else:
files.append(item)
except:
# 出错, 比如没有权限
#traceback.print_exc()
error = top
yield dirs, files, error
if dirs:
sub_stack.put(dirs)
dirs = []
files = []
error = None
代码长度double了.........
os.walk是原本是一个递归. 下面是它的代码:
273 try:
274 # Note that listdir and error are globals in this module due
275 # to earlier import-*.
276 names = listdir(top)
277 except error, err:
278 if onerror is not None:
279 onerror(err)
280 return
281
282 dirs, nondirs = [], []
283 for name in names:
284 if isdir(join(top, name)):
285 dirs.append(name)
286 else:
287 nondirs.append(name)
288
289 if topdown:
290 yield top, dirs, nondirs
291 for name in dirs:
292 path = join(top, name)
293 if followlinks or not islink(path):
294 for x in walk(path, topdown, onerror, followlinks):
295 yield x
296 if not topdown:
297 yield top, dirs, nondirs
BTW:: 这里需要注意*nux的ENAMETOOLONG 错误.
递归无法按"层"历遍目录. 它只能一条一条路径走尽.
朋友说使用循环也可以实现递归, 这种代码从来没有写过. 也一直在迷惑。
但是受 http://www.devshed.com/c/a/Python/Basic-Threading-in-Python/2/ 的启发.
突然明白循环是怎么做到递归的。 于是自己使用循环自己写了一个历遍的函数:
def loop_walk(top, n):
stack = Queue.Queue()
sub_stack = Queue.Queue()
dirs = []
files = []
error = None
stack.put([top])
while True:
if stack.empty():
# stack被取完了, 下一层队列
stack, sub_stack = sub_stack, stack
if n <= 1:
yield [], [], None
return
else:
n -= 1
continue
else:
try:
top_list = stack.get(False)
except Queue.Empty:
yield [], [], None
return
for top in top_list:
try:
for item in os.listdir(top):
item = os.path.join(top, item)
if os.path.isdir(item):
dirs.append(item)
else:
files.append(item)
except:
# 出错, 比如没有权限
#traceback.print_exc()
error = top
yield dirs, files, error
if dirs:
sub_stack.put(dirs)
dirs = []
files = []
error = None
代码长度double了.........
Subscribe to:
Posts (Atom)