Python実行時にプロセス内部情報を動的に表示

2463 ワード

前の2つの「実行時にスレッド情報を表示」のブログに続いて、スレッド情報をいつでも印刷できる以上、プロセス内の他の情報をいつでも印刷できるのではないかと思っています.たとえば、オブジェクトのプロパティをリアルタイムで表示するなど、アプリケーションを再起動せずにプロセスの実行状態を観察できます.(ここではサードパーティ製ライブラリやツールを使用する場合はしばらく考慮しません)
このアイデアに基づいてpythonのダイナミックロードモジュールの方法を見てみると、このアイデアはやはり頼りになると感じて、実現できるはずなので、小さなテストを書いて検証しました.△ここで説明しますが、検証的なもので、生産環境を使うには、まだ多くの問題が考えられます.
次はテスト時に考えなければならないことです.
  • は、SIGQUIT信号である「kill-3」を用いる、印刷プロセスの内部オブジェクト属性の実行をトリガする.
  • foo.pyメインプログラムは、登録信号処理関数を含み、グローバルなオブジェクトを作成してプロパティを保存し、メインスレッドが終了しないようにスレッドを起動します.
  • foo.pyメインプログラムの信号処理関数は、指定されたパスの下のモジュールを動的にロードします.ここで、このモジュールパスは「/tmp/my_modules」であり、必要に応じて変更できると仮定します.次に、このモジュールのメソッドを呼び出して、プロセス情報を印刷します.
  • /tmp/my_modules/bar.pyはfooモジュールのオブジェクトにアクセスし、オブジェクトのプロパティを印刷する動的にロードするモジュールが必要です.
  • は、表示するプロセスの状態を随時動的に変更する、すなわち、プロセスを再起動しない場合にbarを変更する.pyファイルは、表示を実装する内容を変更します.

  • メインプログラムfoo.py
    #!/usr/bin/env /usr/bin/python3.4
    # -*- coding: utf-8 -*-
    import sys
    import threading
    import signal
    from datetime import datetime
    import time
    
    
    class MyObject(object):
        def __init__(self):
            self.data = {}
            self.data['a'] = 'aaa'
            self.data['b'] = 'bbb'
            self.data['c'] = 'ccc'
    
    
    def test():
        while True:
            print(datetime.now())
            time.sleep(2)
    
    #       
    def signal_handler(signum, frame):
        try:
            #       
            sys.path.append("/tmp/my_modules")
    
            #   bar  
            bar = __import__('bar')
    
            #       ,             
            reload(bar)
    
            #            
            bar.execute()
        except BaseException as e:
            print(e)
    
    
    my_object = MyObject()
    
    if __name__ == "__main__":
        try:
            signal.signal(signal.SIGQUIT, signal_handler)
    
            threading.Thread(target=test).start()
    
            while True:
                time.sleep(60)
        except KeyboardInterrupt:
            sys.exit(1)
    

    動的ロードが必要なモジュール/tmp/my_modules/bar.py
    #!/usr/bin/env /usr/bin/python3.4
    # -*- coding: utf-8 -*-
    import foo
    
    
    def execute():
        #   foo      
        print "my_object: %s " % foo.my_object.data
    
    

    テスト
    まずfooを実行する.py
    $ python foo.py
    

    そしてfooを見つけた.pyのプロセス番号を使用し、「kill-3」を使用してメモリオブジェクトの印刷をトリガーする方法
    $ kill -3 
    

    このときfooが見えるはずです.pyプロセス印刷my_objectのプロパティ.
    変更/tmp/my_modules/bar.pyファイルを再実行し、「$kill-3」を再度実行すると、モジュールが再ロードされ、印刷された新しい内容が表示されます.