RuntimeError: Trabalho fora do contexto da aplicação. com app.app_context () não resolver o problema

votos
0

Eu estou tentando executar um demorado ciclo por ter um pool de processos de trabalho sobre ele usando pool.map. O ciclo é uma parte de uma função de visualização que eu tenha colocado em uma nova função para que possa transmiti-lo para pool.map. Mas isso gera o erro -

RuntimeError: Trabalho fora do contexto da aplicação.

Isso normalmente significa que você tentou usar a funcionalidade que precisava para fazer a interface com o objeto do aplicativo atual, de alguma forma. Para resolver isso, criar um contexto de aplicação com app.app_context (). Veja a documentação para mais informações.

Eu fiz colocar a chamada de método em um with app.app_context()(como mencionado aqui ). Mas o erro não foi embora. Por favor me diga como posso resolver esse problema.

@app.route('/some_url', methods= ['POST'])
def view_function ():
    start_time = time.time()
    data = request.get_json()
    a = round(data.get('a', '') * data.get('a', ''))
    b = round(data.get('b', '') * data.get('b', ''))
    c = round(data.get('c', '') * data.get('c', ''))
    d = round(data.get('d', '') * data.get('d', ''))

    a_id = select.get_id(data.get('property', ''), session['somedata'][1])
    some_list, a_ids, loc = AnotherClassInDifferentDir.get_list(a_id, session['somedata'][1])
    value = select.get_value(//some arguments)

Isto é onde uso multiprocessamento, e onde I utilizando with app.app_context():(Esta é uma parte da mesma função, view_function) -

    with app.app_context():
        e = data.get('e', '')
        stuff = session['somedata'][1]
        pool = Pool(processes = 2)
        func = partial(loopTask,e, a_id, a_ids, a, b, c, d, loc, stuff)
        stuff_array = [(index, item) for index, item in enumerate(some_list)]
        print(stuff_array =, stuff_array)
        pool.map(func, stuff_array)
        pool.close()
        pool.join()

    print(--- %s seconds --- % (time.time() - start_time))
    return ''

def loopTask(e, a_ids, a, b, c, d, loc, stuff, stuff_item):

    index, s = stuff_item
    c_id = document_ids[index]
    done = AnotherClassInDifferentDir.work(s)
    f = AnotherClassInDifferentDir.more_work(done, a, b, c, d, loc)
    if f != '':
        update.update_work(//some arguments)
        g.cnxn.commit()
        if (moreDB.check(//some arguments) ==0):
            update.work(//some arguments)
            g.cnxn.commit()
    else:
        pass

Eu acredito que o g.cnxn.commit()está causando esse problema, uma vez que é exposta pelo contexto de aplicação, mas não tenho certeza. Por favor ajude!

Publicado 14/02/2020 em 00:03
fonte usuário
Em outras línguas...                            


1 respostas

votos
1

Como indicado no frasco docs , o contexto aplicativo não está disponível fora de um pedido que é o que acontece quando o loopTaské executado em um processo diferente. Considere passar o seu exemplo aplicativo para a loopTaskfunção e enrole as seções do código sob ele que usam o gobjeto namespace dentro do seu com o bloco. Não realmente precisa do withdentro do bloco do seu view_functiondesde um contexto de aplicativo já existe durante o pedido.

EDIT: Porque nós estamos configurando uma conexão db antes de cada pedido, vamos ficou com um test_request_context. Você pode ler mais sobre isso aqui . É concebido para testar, mas para os nossos propósitos, vai permitir-nos ter uma conexão db no processo gerado.

def loopTask(e, a_ids, a, b, c, d, loc, stuff, stuff_item, app):  # added app parameter 

    index, s = stuff_item
    c_id = document_ids[index]

    with app.test_request_context('/some_url'):
        app.preprocess_request()  # triggers 'connect_to_database'

        done = AnotherClassInDifferentDir.work(s)
        f = AnotherClassInDifferentDir.more_work(done, a, b, c, d, loc)
        if f != '':
            update.update_work(//some arguments)
            g.cnxn.commit()
            if (moreDB.check(//some arguments) ==0):
                update.work(//some arguments)
                g.cnxn.commit()
        else:
            pass

Isto significa então que as withalterações bloco para:

    e = data.get('e', '')
    stuff = session['somedata'][1]
    pool = Pool(processes = 2)
    func = partial(loopTask,e, a_id, a_ids, a, b, c, d, loc, stuff, stuff_item)
    stuff_array = [(index, item) for index, item in enumerate(some_list)]
    print("stuff_array =", stuff_array)
    pool.map(func, (stuff_array, app))  # passing the `app` Flask instance here
    pool.close()
    pool.join()

Isso deve fazer o truque, mas idealmente, deveríamos ter a configuração da conexão db em uma função que pode reutilizar no nosso loopTask. Dessa forma, não seria necessário o test_request_contexte usar app_contextem seu lugar.

Respondeu 14/02/2020 em 00:41
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more