

Pythonのwith文はファイルI/Oに関してよく見かけますが，それ以外に使い方があるのでしょうか？`with open('myfile') as
f:`以外で，with文を使うべき，または使っているのを見かけた例は何かありますか？


CC BY-SA 3.0
2015-01-25T19:42:58.433
5271
2018-11-23T00:23:56.323
2015-01-27T08:58:54.877
565
565
question
python
"with"文のファイルI/O以外の使い方


後処理しないとリソースの残る物であればなんでも良いのではないでしょうか。  
python2.7 の標準添付ライブラリを軽く調べてみた感じ

  * unit テストライブラリの開始と終了をハンドリングしている (unittest)
  * プロセスの管理、およびプロセス間通信の同期をハンドリングしている (multiprocessing)

で使っている様です。実際には `__enter__` と `__exit__`
が宣言されていればユーザ定義オブジェクトでも使用出来るので、個人的にはどんどん使っていったら良いと思います。


CC BY-SA 3.0
2015-01-26T00:17:56.903
5277
2015-01-26T00:17:56.903
440
5271
answer


既に出ているmattnさんの回答にあるように「後処理」が必要ならところには便利です。

以下のような実装がある場合:

[code]

    cwd = os.getcwd()
    os.chdir('/tmp/foo')
    try:
        run()  # 何か
    finally:
        os.chdir(cwd)
    
[/code]

withで使えるように次のようなcdを実装して:

[code]

    @contextlib.contextmanager
    def cd(target_dir):
        cwd = os.getcwd()
        try:
            os.chdir(target_dir)
            yield
        finally:
            os.chdir(cwd)
    
[/code]

以下のように使えます:

[code]

    with cd('/tmp/foo'):
        run()  # 何か
    
[/code]

Fabricでwithを使う例がいくつかあります <http://docs.fabfile.org/en/latest/tutorial.html>


CC BY-SA 3.0
2015-01-26T00:41:36.700
5279
2015-01-26T00:41:36.700
806
5271
answer


`threading.Lock`を使うときはほぼ必ず`with`を使うと思います:

[code]

    class Foo(object):
      def __init__(self):
        self.lock = threading.Lock()
    
      def Bar(self):
        with self.lock:
          # atomic operation
    
[/code]

`with`が使えて便利というのではなく、`with`を **使うべき** ケースでしょう。


CC BY-SA 3.0
2015-01-27T08:36:30.137
5413
2015-01-27T08:36:30.137
2521
5271
answer


既出ではないものとしては、DB のトランザクションを扱うコンテキストでもよく見かけます。

[code]

    import sqlite3
    
    con = sqlite3.connect(":memory:")
    con.execute("create table person (id integer primary key, firstname varchar unique)")
    
    # Successful, con.commit() is called automatically afterwards
    with con:
        con.execute("insert into person(firstname) values (?)", ("Joe",))
    
    # con.rollback() is called after the with block finishes with an exception, the
    # exception is still raised and must be catched
    
[/code]

<http://docs.python.jp/2.7/library/sqlite3.html#id11>


CC BY-SA 3.0
2015-01-29T21:33:43.300
5586
2015-01-29T21:33:43.300
2520
5271
answer


Python3で新たに標準パッケージに入ったmockモジュールのpatchもよく使います。

<http://docs.python.jp/3/library/unittest.mock.html#quick-guide>

モック当てたものは必ず戻さないと他のテストに影響をあたえてしまうのでwithを使うべきものですね。


CC BY-SA 3.0
2015-02-05T06:55:43.250
5979
2015-02-05T06:55:43.250
8090
5271
answer


既出以外だと pytest でも使います。

[code]

    import pytest
    
    def test_zero_division():
        with pytest.raises(ZeroDivisionError):
            1 / 0
    
[/code]

参考: [Assertions about expected
exceptions](http://pytest.org/latest/assert.html#assertions-about-expected-
exceptions)


CC BY-SA 3.0
2015-02-19T09:45:08.540
6768
2015-02-19T09:45:08.540
5997
5271
answer


trio で非同期処理のスコープを限定したい場合にも使います。


CC BY-SA 4.0
2018-11-23T00:23:56.323
50550
2018-11-23T00:23:56.323
5997
5271
answer