with
Pythonのステートメントを使用して複数の変数を宣言することは可能ですか?
何かのようなもの:
from __future__ import with_statement
with open("out.txt","wt"), open("in.txt") as file_out, file_in:
for line in file_in:
file_out.write(line)
...または問題を同時に2つのリソースをクリーンアップしていますか?
with
Pythonのステートメントを使用して複数の変数を宣言することは可能ですか?
何かのようなもの:
from __future__ import with_statement
with open("out.txt","wt"), open("in.txt") as file_out, file_in:
for line in file_in:
file_out.write(line)
...または問題を同時に2つのリソースをクリーンアップしていますか?
回答:
Python 3 ではv3.1と Python 2.7 以降で可能です。新しいwith
構文は、複数のコンテキストマネージャーをサポートします。
with A() as a, B() as b, C() as c:
doSomething(a,b,c)
異なりcontextlib.nested
、この保証はそのa
とb
その必要があります__exit__()
「と呼ばれていてもsのC()
か、それの__enter__()
メソッドが例外を発生させます。
以前の変数を後の定義で使用することもできます(以下のh / t Ahmad)。
with A() as a, B(a) as b, C(a, b) as c:
doSomething(a, c)
with open('./file') as arg.x = file:
ですか?
as
オプションであることに注意してください。
as
オブジェクトa
またはが必要な場合は必須ですb
が、全体as a
またはas b
必須ではありません
contextlib.nested
これをサポートします:
import contextlib
with contextlib.nested(open("out.txt","wt"), open("in.txt")) as (file_out, file_in):
...
更新:
ドキュメントについて引用するにはcontextlib.nested
:
バージョン2.7で非推奨:with-statementがこの機能を直接サポートするようになりました(紛らわしいエラーを起こしやすい癖なしで)。
詳細については、RafałDowgirdの回答を参照してください。
nested
コンテキストマネージャは間違いであり、使用すべきではないと思います。この例では、2番目のファイルを開くと例外が発生した場合、最初のファイルはまったく閉じられないため、コンテキストマネージャを使用する目的が完全に破壊されます。
with
ブロック。マネージャーはwithブロックに入る前に順番に作成されます:m1、m2、m3 = A()、B()、C()B()またはC()が例外で失敗した場合、A( )はガベージコレクタです。
変数を行に分割する場合、バックスラッシュを使用して改行をラップする必要があることに注意してください。
with A() as a, \
B() as b, \
C() as c:
doSomething(a,b,c)
代わりにPythonがタプルを作成するため、括弧は機能しません。
with (A(),
B(),
C()):
doSomething(a,b,c)
タプルには__enter__
属性がないため、エラーが発生します(説明がなく、クラスタイプを識別しません)。
AttributeError: __enter__
as
括弧内で使用しようとすると、Pythonは解析時に間違いを見つけます。
with (A() as a,
B() as b,
C() as c):
doSomething(a,b,c)
SyntaxError:無効な構文
https://bugs.python.org/issue12782がこの問題に関連しているようです。
代わりにこれを実行したいと思います。
from __future__ import with_statement
with open("out.txt","wt") as file_out:
with open("in.txt") as file_in:
for line in file_in:
file_out.write(line)
Python 3.3以降でExitStack
は、contextlib
モジュールのクラスを使用できます。
動的な数のコンテキスト対応オブジェクトを管理できます。つまり、処理するファイルの数がわからない場合に特に役立ちます。
ドキュメントに記載されている正規のユースケースは、動的な数のファイルの管理です。
with ExitStack() as stack:
files = [stack.enter_context(open(fname)) for fname in filenames]
# All opened files will automatically be closed at the end of
# the with statement, even if attempts to open files later
# in the list raise an exception
以下に一般的な例を示します。
from contextlib import ExitStack
class X:
num = 1
def __init__(self):
self.num = X.num
X.num += 1
def __repr__(self):
cls = type(self)
return '{cls.__name__}{self.num}'.format(cls=cls, self=self)
def __enter__(self):
print('enter {!r}'.format(self))
return self.num
def __exit__(self, exc_type, exc_value, traceback):
print('exit {!r}'.format(self))
return True
xs = [X() for _ in range(3)]
with ExitStack() as stack:
print(stack._exit_callbacks)
nums = [stack.enter_context(x) for x in xs]
print(stack._exit_callbacks)
print(stack._exit_callbacks)
print(nums)
出力:
deque([])
enter X1
enter X2
enter X3
deque([<function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86158>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f861e0>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86268>])
exit X3
exit X2
exit X1
deque([])
[1, 2, 3]
Python 3.1以降では、複数のコンテキスト式を指定でき、それらは複数のwith
ステートメントがネストされているかのように処理されます。
with A() as a, B() as b:
suite
に相当
with A() as a:
with B() as b:
suite
これは、最初の式のエイリアスを2番目の式で使用できることも意味します(db接続/カーソルを操作するときに役立ちます)。
with get_conn() as conn, conn.cursor() as cursor:
cursor.execute(sql)