5

2つのPythonスクリプトA.pyとがありB.pyます。次のような方法でA内からBを実行する方法を探しています。

  1. Bはそれを信じています( Bのブロック内__main__のコードが実行されるように)if __name__=="__main__"
  2. Bは実際にはそうではありません(たとえば、 sys.modules__main__のエントリを上書きしないように)"__main__"
  3. B内で発生した例外はAに伝播します(つまり、exceptAの句でキャッチされる可能性があります)。
  4. これらの例外がキャッチされない場合、B内の行番号を参照する正しいトレースバックが生成されます。

私はさまざまなテクニックを試しましたが、すべての要件を満たすものはないようです。

  • サブプロセスモジュールのツールを使用するということは、Bの例外がAに伝播しないことを意味します。
  • execfile("B.py", {})Bを実行しますが、メインではないと思います。
  • execfile("B.py", {'__name__': '__main__'})B.pyにそれがメインであると思わせますが、例外のトレースバック印刷を台無しにしているように見えるため、トレースバックはA内の行(つまり、実際の__main__)を参照します。
  • imp.load_source名前としてwithを使用すると__main__、実際にsys.modulesが変更されることを除いて、ほとんど機能します。__main__

私が欲しいものを手に入れる方法はありますか?

(これを行う理由は、既存のライブラリをクリーンアップしているためです。このライブラリには実際のテストスイートはなく、特定の出力を生成する一連の「サンプル」スクリプトのみがあります。これらを次のように活用しようとしています。クリーンアップがこれらの例を実行するライブラリの機能に影響を与えないことを確認するためのテストなので、テストスイート内から各サンプルスクリプトを実行したいと思います。テストスクリプト内でこれらのスクリプトの例外を確認できるようにしたいので、テストスクリプトは、サンプルスクリプトで例外が発生するたびに、一般的なSubprocessErrorを報告するだけでなく、失敗のタイプを報告できます。)

4

2 に答える 2

2

結果は興味深いものであり、他の人にも役立つ可能性があるため、私自身の質問に答えます。

私が間違っていたことが判明しました:execfile("B.py", {'__name__': '__main__'}結局のところ行く方法です。トレースバック正しく生成されます。間違った行番号で私が見たのは例外ではなく警告でした。これらの警告は、を使用して生成されましwarnings.warn("blah", stacklevel=2)た。このstacklevel=2引数は、警告呼び出しではなく、非推奨のものが使用されている場所で非推奨警告などを発生させることができるようになっています(ドキュメントを参照)。

ただし、execfile-dファイルは、この目的では「スタックレベル」としてカウントされず、目的からは見えないようですstacklevel。したがって、execfile-dモジュールのトップレベルのコードがスタックレベル2で警告を発生させた場合、警告はexecfile-dソースファイルの正しい行番号で発生しません。代わりに、execfileを実行しているファイルの対応する行番号で発生します。

これは残念なことですが、これらは単なる警告であり、テストの実際のパフォーマンスに影響を与えることはないので、私はそれを受け入れることができます。(テスト出力には多くの警告と例外が混在していたため、行番号の不一致の影響を受けたのは警告だけであることに最初は気づきませんでした。)

于 2012-07-06T07:24:45.810 に答える
2

あなたのユースケースは理にかなっていますが、外部で実行できるようにテストをリファクタリングする方がよいと思います。

スクリプトにこのようなものがあることをテストしますか?

def test():
    pass

if __name__ == '__main__':
    test()

そうでない場合は、テストを などの関数の呼び出しに変換する必要がありますtest。次に、メインのテスト スクリプトから、次のことができます。

import test1
test1.test()
import test2
test2.test()

テスト自体が使用する、実行中のテストに共通のインターフェイスを提供します。チェックに大きなコード ブロックがあることは、__main__良いことではありません。

ご質問にお答えできなくて申し訳ありませんが、元のテスト コードから大きく逸脱することなく、これが正しい解決策だと思います。

于 2012-07-06T07:08:41.267 に答える