Python中使用subprocess的上下文管理器简单解释是什么?

0 投票
2 回答
1494 浏览
提问于 2025-04-18 09:14

我是一名活跃的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()呢?

2 个回答

0

这要看你在子进程中想要做什么。如果你只是想执行一些不需要互动的命令,使用os.system()就可以了。但很多时候,你可能需要或想要读取输出信息(stdout)和错误信息(stderr),并且希望子进程能和主进程同时运行。使用上下文管理器会更灵活,适合处理比简单命令执行更复杂的情况。

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

(这个代码完全没有测试,可能根本不能用。我只是快速查看了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模块)。你关注的这些特定例子恰好比较复杂,因此更能体现面向对象编程和上下文管理器带来的好处。

撰写回答