Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中带有子流程的上下文管理器的简单解释是什么?_Python - Fatal编程技术网

Python中带有子流程的上下文管理器的简单解释是什么?

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

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

这取决于您在子进程中试图完成什么。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
执行子流程会很好(尽管通常我建议使用
子流程
模块)。不过,您所看到的特定示例恰好要复杂得多,并且受益于面向对象编程和上下文管理器提供的抽象。

您能给出一个具体示例(带代码)来说明您所说的内容吗?使用
子流程
模块而不是
操作系统
是有原因的,但我不确定上下文管理器是如何分解到您的问题中的。您应该始终使用来自子流程的调用,它还提供“简单”接口(例如调用或检查),这样您就始终使用一致的模块进行流程管理。