我在使用PyYAML从yaml文件输入的打印信息时遇到问题。我正在尝试减少行数,而不会影响功能。在某些运行中,输出必须附加到文件中,而在其他运行中附加到stdout。
起初我在我的函数 processData :
中多次使用它labels
这很有效,但是当出现问题时,它的缺点是不使用 with 语句。
实际问题不是复杂的印刷语句,而是我
1)打印到文件或sys.stdout时不想复制代码 2)想要使用 with 语句,以便在出现打印错误时关闭文件 3)有几个这样的块,我不想为每个块调用不同的函数,因此防止代码重复
然后我尝试的是:
if logName:
fp = open(logName, 'a')
else:
fp = sys.stdout
print(........, file=fp)
print(........, file=fp)
if logName:
fp.close()
如果没有logName,则此错误为“ValueError:对已关闭文件的I / O操作”。有关如何在没有原始复制的情况下使其工作的任何建议?我可以重新打开sys.stdout吗?
答案 0 :(得分:2)
您可以在类中“包装”sys.stdout
以防止它首先被关闭。
with
语句在开头和结尾分别对该类的实例调用__enter__
和__exit__
,因此请确保__exit__
不执行任何操作:
class StdOut:
def __enter__(self):
return sys.stdout
def __exit__(self, typ, val, trace):
pass
stdout = StdOut()
然后使用stdout
代替sys.stdout
答案 1 :(得分:1)
在最低C级别, stdout 是众所周知的file descriptor(指向运行时或系统管理的描述符表中的条目的整数),在进程中初始化在它的创作。 It cannot be reopened (with standard C means) once it's closed and must be duplicated beforehand if you still need it.
可以像这样创建sys.stdout
的一次性副本:
stdout_copy=os.fdopen(os.dup(sys.stdout.fileno()),sys.stdout.mode)
(在Python 3中,os.fdopen()
已合并到open()
并且是它的别名。)
如果sys.__stdout__
已被替换,您可能需要使用sys.stdout
。
with
逻辑首先,考虑标准的标准方法 - 即logging
模块 - 以避免重新发明方形轮。按需打开和关闭文件可以很好地用它的机器实现,在绝大多数情况下甚至都不需要它。
现在,削减代码重复部分的唯一方法是将重复部分包装到子例程中(或者处理列表的代码块,其中的元素描述了每次迭代应该执行的操作,但它只能是用过一次)。这里有三个概念部分,无论语法如何(try
/ finally
都与with
一样):
仅包含“开始+结束代码”是最简单的,the other answer是一种可能的方式,但它会留下重复的with
和print(........, file=fp)
部分。
包装整个结构更难,因为你必须将代码块传递给你想要的子程序,而Python故意省略匿名代码块 - 你必须def
然后立即使用它相当尴尬。