Python中带有子流程的上下文管理器的简单解释是什么?
我是一个活跃的python用户,似乎互联网上的大多数教程都会向我介绍一个上下文管理器,它有一个子流程来处理通过python执行二进制文件,例如使用exiftool读取图像exif数据Python中带有子流程的上下文管理器的简单解释是什么?,python,Python,我是一个活跃的python用户,似乎互联网上的大多数教程都会向我介绍一个上下文管理器,它有一个子流程来处理通过python执行二进制文件,例如使用exiftool读取图像exif数据 def readExif(fname): with ExifTool() as e: try: metadata = e.get_metadata(fname) metadata = metadata[0] except Uni
def readExif(fname):
with ExifTool() as e:
try:
metadata = e.get_metadata(fname)
metadata = metadata[0]
except UnicodeDecodeError:
return False
for f in files:
print readExif(f)
这是我的问题(从一个真正的初学者的角度):为什么我不能只使用os.system()?这取决于您在子进程中试图完成什么。os.system()可以执行不需要交互的任务,但通常需要或希望能够读取stdout/stderr并与主进程并行运行子进程。除了简单的子命令执行之外,使用上下文管理器更加灵活,能够处理所有事情 ExifTool装饰器只是删除了大量的样板文件和错误处理,您需要使用类似于
os.system()
的工具直接可靠地处理调用ExifTool可执行文件。即使您直接使用subprocess.Popen
,这比os.system
更高级,您的代码看起来也类似于ExifTool
提供的功能:
with open(os.devnull, "w") as devnull:
_process = subprocess.Popen(
[self.executable, "-stay_open", "True", "-@", "-",
"-common_args", "-G", "-n"],
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=devnull)
try:
_process.stdin.write(b"\n".join([filename] + (b"-execute\n",)))
_process.stdin.flush()
output = b""
fd = _process.stdout.fileno()
sentinel = b"{ready}"
while not output[-32:].strip().endswith(sentinel):
output += os.read(fd, block_size)
metadata = output.strip()[:-len(sentinel)][0]
metadata = metdata[0]
except UnicodeDecodeError:
return False
finally:
_process.stdin.write(b"-stay_open\nFalse\n")
_process.stdin.flush()
_process.communicate()
del _process
(这是完全未经测试的,可能不会起作用。我只是快速查看了pyexiftool的应用程序,将其组合在一起。)
正如你所看到的,那里发生了很多事情。上下文管理器本身处理try
块之前的所有内容,以及整个finally
块。如果您希望使用ExifTool
,而不将其用作上下文管理器,但具有等效功能,则它将如下所示:
e = ExifTool()
e.start()
try:
metadata = e.get_metadata(fname)
metadata = metadata[0]
except UnicodeDecodeError:
return False
finally:
e.terminate()
您可以通过查看ExifTool.\uuuu enter\uuuuu()
和ExifTool.\uuuu exit\uuuuu()
来确认这一点,这两种方法分别是当您使用ExifTool()作为e:块输入和退出时调用的方法
当然,在许多简单的情况下,直接使用os.system
执行子流程会很好(尽管通常我建议使用子流程
模块)。不过,您所看到的特定示例恰好要复杂得多,并且受益于面向对象编程和上下文管理器提供的抽象。您能给出一个具体示例(带代码)来说明您所说的内容吗?使用子流程
模块而不是操作系统
是有原因的,但我不确定上下文管理器是如何分解到您的问题中的。您应该始终使用来自子流程的调用,它还提供“简单”接口(例如调用或检查),这样您就始终使用一致的模块进行流程管理。