在没有 'with' 的情况下使用上下文对象是否应该工作?

Should a context object work when used without 'with'?

我不太确定如何为自定义 class 实施上下文管理器。基本上它只是在 __init__ 中接受一个文件名,在 __enter__ 中打开文件并在 __exit__ 中关闭它。

例如:

class BlaFile:
    def __init__(self, file_name):
        self.file_name = file_name

    def __enter__(self):
        self.file = open(self.file_name, "rb")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()

    def do_stuff_with_file():
        # This will fail when I'm using this class without 'with'.
        return self.file.read(1)

但是,当我不打算用 'with' 语句实例化/使用 class 时,我将无法使用它访问文件的任何函数,因为 __enter__从未被调用过;因此文件未打开。

也许我在这里过于偏向 C# 的 using 关键字;但是我不应该能够正确使用 class 的实例,即使我没有将它与 with 关键字一起使用吗?现在我不得不和它一起使用 - 这是 Python 中的典型用法吗?

你需要使用open() 要以阅读方式打开,您需要更改为:

class BlaFile:
    def __init__(self, file_name):
        self.file_name = file_name
        self.file = open(self.file_name, "r+b")
    def close(self):
        self.file.close()

    def do_stuff_with_file(self):
        return self.file.read(1)

这应该可以解决问题。

如果您希望文件无论是否在 with 中使用都被打开,您需要在 __init__ 方法中打开文件。由于用户可能会忘记关闭文件,我建议您将关闭注册为在退出时发生:

from atexit import register

class BlaFile:
    def __init__(self, file_name):
        self.file_name = file_name
        self.file = open(file_name, 'rb')
        register(self.file.close)

    def __enter__(self):
        pass

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()

    def do_stuff_with_file(self):
        return self.file.read(1)