Быстрее тесты с анализом зависимостей


У меня есть проблема с производительностью результате тест->код->цикл испытаний, чтобы быть очень медленным. Медлительность трудно избежать, так как я занимаюсь тяжелой обработки изображений, и я пытаюсь ускорить вещи немного, не работает функции, когда он не нужен. Например: вычислить некоторые цифры из большой изображения -> сериализовать результаты в текстовых файлах -> продолжить вычисления из текстовых файлов.

В настоящее время, я предаю это текстовые файлы, содержащие результаты, чтобы делиться ими с командой, и пусть другие люди быстро выполнить тесты. Но я должен убедиться, что всякий раз, когда одна зависимость обновляется (ЦСИ изображений, предварительной обработки функций и т. д.), Эти значения вычисляются. Я искал инструмент, который позволил бы мне, чтобы описать зависимости и правила производства автоматизировать процесс и избежать совершения данных в коде. Я думал о Makefile, но я читаю много негативных совет против него. Я нашел вещи, как проектов SCons и другие построения инструментов автоматизации, но и тех, которые предназначены для создания программного обеспечения, и они не кажутся адаптированными для моих задач.

Я решил написать небольшой lib для решения этой проблемы (мое окружение в основном на Python и некоторые с). Цель в том, чтобы объекты, зная продукционных правил для их собственного выхода, и в курсе других предметов, они зависят от. Объект знает, что если его выход актуальную на сравнение текущей контрольной суммы MD5 файла от последняя (хранится где-то в небольшом временном файле).

Я изобретать здесь колесо? Существует ли инструмент там, что я должен использовать вместо пользовательской Либ? Если нет, то это хорошая картина для ухода от этой проблемы?

import os
import path
from md5 import md5 as stdMd5

# path.root is the root of our repo
hashDir = os.path.join(path.root, '_hashes')

def md5(toHash):
    return stdMd5(toHash).hexdigest()

class BaseRule(object):
    '''base object, managing work like checking if results are up to date, and
    calling production rules if they are not'''

    outPath = None

    def __init__(self, func):
        self.func = func

    @property
    def hashPath(self):
        return os.path.join(hashDir, md5(self.outPath))

    def getOutHash(self):
        with open(self.outPath) as f:
            fileHash = md5(f.read())
        return fileHash

    def isUpToDate(self):
        if not os.path.exists(self.outPath):
            return False
        if not os.path.exists(self.hashPath):
            return False
        with open(self.outPath) as f:
            fileHash = self.getOutHash()
        with open(self.hashPath) as f:
            storedHash = f.read().strip()
        return storedHash == fileHash

    def storeHash(self):
        if not os.path.exists(hashDir):
            os.makedirs(hashDir)
        with open(self.hashPath, 'w') as f:
            f.write(self.getOutHash())

    def get(self):
        inputPathes = dict([(key, inp.get()) for key, inp in self.inputs.items()])
        if not self.isUpToDate():
            self.func(outPath=self.outPath, **inputPathes)
            self.storeHash()
        return self.outPath

class StableSrc(BaseRule):
    'source file that never change'

    inputs = {}

    def __init__(self, path):
        self.outPath = path

    def isUpToDate(self):
        return True


def rule(_inputs, _outPath):
    'decorator used to declare dependencies'

    class Rule(BaseRule):
        inputs = _inputs
        outPath = _outPath

    return Rule

def copyTest():
    'test function'

    import shutil

    @rule({'inp' : StableSrc('test.txt')}, 'test2.txt')
    def newTest(inp, outPath):
        print 'copy'
        shutil.copy(inp, outPath)


    @rule({'inp' : newTest}, 'test3.txt')
    def newNewTest(inp, outPath):
        print 'copy2'
        shutil.copy(inp, outPath)

    return newNewTest.get()

if __name__ == '__main__':
    copyTest() # will copy test.txt to test2.txt and test3.txt. If ran a second time, won't copy anything


274
5
задан 20 сентября 2011 в 12:09 Источник Поделиться
Комментарии
1 ответ

# path.root is the root of our repo
hashDir = os.path.join(path.root, '_hashes')

Руководство по стилю Python рекомендует глобальной константы, что написано заглавными_буквами

class BaseRule(object):
'''base object, managing work like checking if results are up to date, and
calling production rules if they are not'''

outPath = None

Руководство по стилю Python рекомендует константы уровне класса, что написано заглавными_буквами

    def isUpToDate(self):
if not os.path.exists(self.outPath):
return False
if not os.path.exists(self.hashPath):
return False
with open(self.outPath) as f:
fileHash = self.getOutHas()

Вы не используете файл вы открываете здесь, вместо того, чтобы открыть файл внутри getOutHash

        with open(self.hashPath) as f:
storedHash = f.read().strip()
return storedHash == fileHash

def get(self):
inputPathes = dict([(key, inp.get()) for key, inp in self.inputs.items()])

Нет необходимости в квадратные скобки. Они делают это так, что он выдает список. Но так как вы создаете словарь, нет необходимости сделать первый список.

        if not self.isUpToDate():
self.func(outPath=self.outPath, **inputPathes)
self.storeHash()
return self.outPath

class StableSrc(BaseRule):
'source file that never change'

inputs = {}

Я знаю, что вы никогда не будете изменить это, но входы в выше уровня атрибута объекта, и его ясное, если вы держите его таким образом.

    def __init__(self, path):
self.outPath = path

def isUpToDate(self):
return True

def copyTest():
'test function'

import shutil

@rule({'inp' : StableSrc('test.txt')}, 'test2.txt')
def newTest(inp, outPath):
print 'copy'
shutil.copy(inp, outPath)

Обычно у вас есть небольшое количество возможных действий с разных входов/выходов для каждого использования. Ваш метод оформитель предполагает, что каждое действие будет отличаться.


  1. Вы не отслеживаете зависимостей между правилами. Так нельзя, как .Свиг производит .КПФ производит .о которой привязана к производству .ехе

  2. Создание класса на каждое правило-это странно. Было бы больше смысла, чтобы создать объект для каждого правила.

  3. Единственное, что у тебя за файлы Makefile является использование хэш, а затем метку

2
ответ дан 20 сентября 2011 в 12:09 Источник Поделиться