34

ctrl-c割り込みを処理するシグナルハンドラがあります。シグナルハンドラーでメインスクリプトに設定された変数を読み取りたい場合、変数を設定するときに「グローバル」ステートメントを使用する代わりの方法はありますか?

私はこれを行ってもかまいませんが、誰かがグローバルを使用する理由はないはずだとコメントしたこの投稿( Pythonで「グローバル」ステートメントを使用しますか? )を読んでください。

この場合の代替案は何ですか?

私のコードは次のようになります。


def signal_handler(signal, frame):
    print "in sig handler - g_var=%s" % g_var

def main():
    global g_var
    g_var = "test"

    time.sleep(120)


if __name__ == '__main__':
    signal.signal(signal.SIGINT, signal_handler)
    main()
4

5 に答える 5

37

メインスクリプトから状態を取得するシグナルハンドラーとしてクロージャーを使用できます。

import signal
import sys
import time

def main_function():

    data_for_signal_handler = 10

    def signal_handler(*args):
        print data_for_signal_handler
        sys.exit()

    signal.signal(signal.SIGINT, signal_handler) # Or whatever signal

    while True:
        data_for_signal_handler += 1
        time.sleep(0.5)

if __name__ == '__main__':
    main_function()
于 2012-09-11T14:08:27.553 に答える
31

partial「クロージャ」を作成するために使用できます。

import signal
from functools import partial

def signal_handler(g_var, signal, frame):
    print "in sig handler - g_var=%s" % g_var

def main():
    g_var = "test"
    signal.signal(signal.SIGINT, partial(signal_handler, g_var))

    time.sleep(120)


if __name__ == '__main__':
    main()
于 2015-07-29T19:06:39.910 に答える
10

オブジェクト指向パラダイム(OOP)内では、その目的でラムダを使用すると非常に便利です。ラムダを使用すると、追加のコンテキスト(自己参照など)を渡したり、未使用の引数(シグナルフレーム)を削除したりできます。

import time
import signal

class Application:

    def __init__( self ):
        signal.signal( signal.SIGINT, lambda signal, frame: self._signal_handler() )
        self.terminated = False

    def _signal_handler( self ):
        self.terminated = True

    def MainLoop( self ):        
        while not self.terminated:
            print( "I'm just doing my job like everyone else" )
            time.sleep( 3 )

app = Application()
app.MainLoop()

print( "The app is terminated, exiting ..." )
于 2017-10-18T12:27:16.583 に答える
1

次のように、インライン定義関数内から外部スコープ変数にアクセスできます。

my_values = {'foo':'bar'}
def handler(signum, frame):
    for key,val in my_values.items():
        print key,val
    my_values['bat']='baz'
    #remember to use mutable types, like dicts or lists

signal.signal(signal.SIGINT, handler)
于 2012-09-11T14:03:38.900 に答える
1

変数を読み取るだけの場合は、変数を「グローバル」にする必要はありません。

def foo():
    print a
a = 3
foo()  #3

変数を変更し、その変更をモジュールの名前空間に反映させるには、globalが必要です。

グローバルを使用せずにコールバックに状態を渡したい場合、これを行う一般的な方法は、コールバックとしてインスタンスメソッドを使用することです。

class foo(object):
     def __init__(self,arg):
         self.arg = arg
     def callback_print_arg(self):
         print self.arg

def call_callback(callback):
    callback()

a = foo(42)
call_callback(a.callback_print_arg) #42
于 2012-09-11T13:57:28.977 に答える