我是一个活跃的python用户,似乎互联网上的大多数教程都指向一个带有子进程的上下文管理器来处理通过python执行二进制文件,例如使用exiftool读取图像exif数据。
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()?
答案 0 :(得分:2)
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
(这是完全未经测试的,可能不会起作用。我只是快速查看了source的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.__enter__()
和ExifTool.__exit__()
来确认这一点,这两种方法分别在您进入和退出with ExifTool() as e:
块时被调用。
肯定有很多简单的情况,直接执行带有os.system
的子进程可以正常工作(尽管一般情况下我建议使用subprocess
模块)。然而,您一直在寻找的特定示例恰好要复杂得多,并且受益于面向对象编程和上下文管理器提供的抽象。
答案 1 :(得分:0)
这取决于您在子进程中要完成的任务。 os.system()适用于执行不需要与之交互的内容,但通常需要或希望能够读取stdout / stderr并与主进程并行运行子进程。使用上下文管理器更加灵活,能够处理简单子命令执行之外的所有事情。