Как упаковать функцию и ее аргумент, чтобы код был чистым и простым

Рабочий код, размещенный ниже, использует Python threading а также queue модуль для инициирования одного MyThread поток, который захватывает входящие данные через глобальный queue объект (список словарей). Каждый словарь данных предназначен для хранения функции, которая будет выполняться MyThread, data словаря function ключ, как ожидается, будет использоваться для передачи функции для запуска. И его function_argument ключ должен использоваться для передачи аргумента функции.

Вместо использования словаря function а также function_argument ключи я бы оценил "упаковать" функцию и ее аргумент в одну переменную или объект, чтобы передать его MyThread? Так MyThread просто взял бы функцию и ее аргументы и просто запустил бы ее с любой дополнительной работой по распаковке словаря данных.

Конечно, я мог бы просто определить исполняемую команду как строку:

cmd = "myFunction(argument = 'Somewhere over the rainbow')"
eval(cmd)

Но это кажется уродливым решением.

import logging
formatter = logging.Formatter("[%(levelname)s] %(asctime)s, %(message)s", "%Y-%m-%d %H:%M:%S")
handler = logging.StreamHandler()
handler.setFormatter(formatter)
log = logging.getLogger(__name__)
log.addHandler(handler)
log.setLevel(logging.DEBUG)

from threading import Thread
import Queue as Queue
global queue
queue = Queue.Queue()


class MyThread(Thread):
    def __init__(self, parent=None):
        Thread.__init__(self, parent)

    def run(self):
        global queue
        while True:
            data = queue.get()

            function = data.get('function')
            argument = data.get('function_argument')

            output = function(argument)

            queue.task_done()
            log.info('MyThread: Task completed. Exiting.')
            exit()


threads = []
thread = MyThread()
threads.append(thread)
thread.start()


def myFunction(argument):
    log.debug('Running myFunction using argument: %r' % argument)

argument = 'Somewhere over the rainbow'
data = {'function': myFunction, 'function_argument': argument}
queue.put(data)

1 ответ

Решение

Просто положить lambda (или же functools.partial) функция в вашей очереди:

data = lambda : myFunction(argument)

или же

import functools
data = functools.partial(myFunction,argument)

затем:

queue.put(data)

тогда используйте как есть:

data = queue.get()
output = data()
Другие вопросы по тегам