Pythonコンテキストマネージャでディレクトリを変更する


Originally published on thomaseckert.dev


私の最新のプロジェクトでは、私はフラスコアプリにTruwindとVueを追加しました.これには、各ビルドをコンパイルするための追加のビルドステップが必要ですnpm 展開中.ビルドステップが発生した時点でサーバにPythonがすでに存在しているとすると、ビルドスクリプトをPythonで書くことにしました.
以前にビルドスクリプトを書いた人は、ディレクトリに変更したり、コマンドを実行したりして、次のコマンドセットを始めるために元のディレクトリに戻ります.それはまさに私がここでする必要がありました.
  • ディレクトリを変更./tailwind
  • 実行するnpm install 依存関係をインストールするには
  • 実行するnpm run build Cookwind CSSをコンパイルするには
  • ディレクトリを変更..
  • ディレクトリを変更./vue
  • 実行するnpm install 依存関係をインストールするには
  • 実行するnpm run build Vueアプリケーションをコンパイルするには
  • これはPythonのコンテキストマネージャにぴったり合うように見えました.コンテキストマネージャを使用してコンテキストのinstatiationを可能にするwith キーワード.コンテキストは、コードがdedentedされたときに配置されます.ここでディレクトリを変更するためにコンテキストマネージャを使用すると、ステップ2で相対パスディレクトリの変更がなくなります.最初のステップが完了すると、ディレクトリが自動的にコンテキストが開始される前にリセットされます.
    右のコンテキストマネージャを書くことによってset_directory , 私はビルドスクリプトを
    from pathlib import Path
    
    with set_directory(Path("./tailwind")):
        run_npm_install()
        run_npm_build()
    with set_directory(Path("./vue")):
        run_npm_install()
        run_npm_build()
    
    そして、私はそれがかなり滑らかであると思いました!
    コンテキストマネージャは、クラスまたは関数として記述できます.この文脈の相対的な単純さを考えれば、私は関数を使うことを選びました.コンテキストマネージャ関数は@contextmanagercontextlib . それにはtry ブロックするyieldfinally ブロック.When the context is instantiated using the with キーワードtry ブロックが実行されます.インデントされたコードブロックが残っている場合、finally ブロックが実行されます.例として
    from contextlib import contextmanager
    
    @contextmanager
    def friendly_context():
        try:
            print("Hello! Welcome to the context!")
            yield
        finally:
            print("Bye now. Thank you for visiting the context. Come again soon.")
    
    with friendly_context():
        print("Oh thank you, it is so nice to be in the context.")
    
    実行時に
    Hello! Welcome to the context!
    Oh thank you, it is so nice to be in the context.
    Bye now. Thank you for visiting the context. Come again soon.
    
    ディレクトリマネージャを変更するには、元のパスを変数に保存し、try 関数に渡されたブロックに対して、finally ブロック.
    from contextlib import contextmanager
    from pathlib import Path
    
    import os
    
    @contextmanager
    def set_directory(path: Path):
        """Sets the cwd within the context
    
        Args:
            path (Path): The path to the cwd
    
        Yields:
            None
        """
    
        origin = Path().absolute()
        try:
            os.chdir(path)
            yield
        finally:
            os.chdir(origin)
    
    そして、それは魅力のように動作します!あなたが文脈管理者のために涼しい使用を見つけたか、この問題を別の方法で解決したならば、知らせてください.