简体   繁体   English

返回然后等待另一个 function 在 python 中完成

[英]Return then wait for another function to finish in python

My general idea is, that I have a or more test functions which can call another function.我的总体想法是,我有一个或多个测试函数可以调用另一个 function。 So:所以:

  1. test_function does some things, then calls another function test_function 做了一些事情,然后调用另一个 function
  2. Called other function will do something, then return a result and调用其他 function 会做一些事情,然后返回一个结果和
  3. Wait for the test_function to finish, then do everything that is to be done after the "return"等待test_function完成,然后做“return”之后要做的所有事情

Of course, that does not work with a literal return, so my question is, if there is a possibility I do not see.当然,这不适用于字面返回,所以我的问题是,如果有可能我看不到。

A practical example:一个实际的例子:

Test function in pytest - test_config is a fixture:在 pytest 中测试 function - test_config 是一个夹具:

def test_load_into_database(test_config):
    logger.info('Testing load_into_database')
    data = {
        'filename': 'file_0'
    }
    accessor = list(database_accessor(test_config))[0]
    access_data = accessor['session'].query(accessor['table']).all()
    assert access_data[0].filename != data['filename']
    accessor['session'].add(accessor['table'](
        filename='file_0'
    ))
    accessor['session'].commit()
    access_data = accessor['session'].query(accessor['table']).all()
    assert access_data[0].filename == data['filename']

This test function calls another one:这个测试 function 调用另一个:

def database_accessor(cfg):
    setup = 'mysql+pymysql://{}:{}@{}/{}'.format(
        cfg['database_user'],
        cfg['database_passwd'],
        cfg['database_host'],
        cfg['database_db']
    )
    Base = automap_base()
    engine = create_engine(setup, echo=False)
    Base.prepare(engine, reflect=True)
    table = Base.classes.get(cfg['database_table'])
    session = Session(engine)
    ->return and wait<- {
        'session': session,
        'table': table
    }
    session.close()
    with engine.connect() as con:
        con.execution_options(autocommit=True).execute("TRUNCATE TABLE {}".format(cfg['database_table']))

What I want is, that the database_accessor returns the dictionary, then waits for the underlying function (in this case the test_function) to finish, then resumes.我想要的是,database_accessor 返回字典,然后等待底层 function(在本例中为 test_function)完成,然后继续。

That way, it is possible to use a variable number of test functions with the same database_accessor without executing all the different test functions in the database_accessor.这样,就可以在同一个 database_accessor 中使用可变数量的测试函数,而无需在 database_accessor 中执行所有不同的测试函数。

Callbacks回调

I know that there is a way, with a callback function, but that doubles my functions, which I do not want.我知道有一种方法,使用回调 function,但这会使我的功能加倍,这是我不想要的。 Eg例如

def test_load_into_database():
    database_accessor(load_into_database_1, var1, var2)

def database_accessor(function, args*):
    # do stuff
    function(args, stuff)
    # do other stuff

def load_into_database_1(args, stuff):
    # do something

I think you'd want to make database_accessor a context manager:我认为您想让database_accessor成为上下文管理器:

with database_accessor(test_config) as accessor:
    access_data = accessor['session'].query(accessor['table']).all()
    assert access_data[0].filename != data['filename']
    accessor['session'].add(accessor['table'](
        filename='file_0'
    ))
    accessor['session'].commit()
    access_data = accessor['session'].query(accessor['table']).all()
    assert access_data[0].filename == data['filename']

The implementation would looks something like this:实现看起来像这样:

from contextlib import contextmanager

@contextmanager
def database_accessor(cfg):
    setup = 'mysql+pymysql://{}:{}@{}/{}'.format(
        cfg['database_user'],
        cfg['database_passwd'],
        cfg['database_host'],
        cfg['database_db']
    )
    Base = automap_base()
    engine = create_engine(setup, echo=False)
    Base.prepare(engine, reflect=True)
    table = Base.classes.get(cfg['database_table'])
    session = Session(engine)
    try:
        yield {
        'session': session,
        'table': table
        }
    finally:
        session.close()
        with engine.connect() as con:
            con.execution_options(autocommit=True).execute("TRUNCATE TABLE {}".format(cfg['database_table']))

In this case, I would modify it slightly to yield a tuple instead of a dict:在这种情况下,我会稍微修改它以产生一个元组而不是一个字典:

yield session, table

and then, when using it you could do:然后,在使用它时,您可以执行以下操作:

with database_accessor(test_config) as (session, table):

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM