简体   繁体   English

如何在 Python 中的 concurrent.futures.ProcessPoolExecutor 中传递“锁”?

[英]How to pass the “lock” in my concurrent.futures.ProcessPoolExecutor in Python?

I am running a parallel test with Python 3.7 and Appium 1.15.1 on real Android smartphones.我正在真正的 Android 智能手机上使用 Python 3.7 和 Appium 1.15.1 运行并行测试。

I use concurrent.futures.ProcessPoolExecutor to run each test on each smartphone.我使用concurrent.futures.ProcessPoolExecutor在每个智能手机上运行每个测试。

I am passing list of the uid of smartphones to my map function.我正在将智能手机的 uid 列表传递给我的 map function。 By this way, my method 'run_smartphone()'(which start the test) get the uid of smartphone and identify on which smartphone it must run the test.通过这种方式,我的方法“run_smartphone()”(启动测试)获取智能手机的 uid 并确定它必须在哪个智能手机上运行测试。

My script work fine without any issue.我的脚本工作正常,没有任何问题。 But I would like to add a "lock" because 'run_smartphone()' make some I/O on a sqlite3 database.我想添加一个“锁” ,因为 'run_smartphone()' 在 sqlite3 数据库上进行一些 I/O。 So correct me if I am wrong, but it would be a good practice to "lock" the I/O operation on this sqlite3 database?如果我错了,请纠正我,但是在这个 sqlite3 数据库上“锁定”I/O 操作是一个好习惯吗?

Here is my original code which works:这是我的原始代码,它有效:

def run_smartphone(p_udid):
    #do the stuff

list_smartphones_connected = [41492968379078, 53519716736397]
with concurrent.futures.ProcessPoolExecutor() as executor:
    try:
        multiprocesses = executor.map(mymodules.run_smartphone, list_smartphones_connected)

    except ValueError:
        print(("Error multiprocesses"))

So I tried to add pass "lock" to my method 'run_smartphone()'.所以我尝试将传递“锁定”添加到我的方法“run_smartphone()”中。 This is what I wrote:这是我写的:

m = multiprocessing.Manager()
lock = m.Lock()
list_arguments_smartphones = []

list_smartphones_connected = [41492968379078, 53519716736397]
for smartphone_connected in list_smartphones_connected:        
    list_arguments_smartphones.append([smartphone_connected, lock])

with concurrent.futures.ProcessPoolExecutor() as executor:
    try:
        multiprocesses = executor.map(mymodules.run_smartphone, list_arguments_smartphones)

    except ValueError:
        print(("Error multiprocesses"))

But it doesn't work and I don't get any exception raised.但它不起作用,我没有提出任何异常。 Pycharm stop the script: Pycharm 停止脚本:

Process finished with exit code 0

I have no idea what is stopping the script.我不知道是什么停止了脚本。

So I started to investigate by executing the script for 1 smartphone with this line:因此,我开始通过使用以下行执行 1 部智能手机的脚本来进行调查:

 multiprocesses = executor.map(mymodules.run_smartphone, [41492968379078,lock])

it gives the same result => The script stop, no automation start and I don't see any exception raised (Process finished with exit code 0).它给出了相同的结果 => 脚本停止,没有自动启动,我没有看到任何异常引发(进程以退出代码 0 完成)。

As I wanted to know where exactly was the issue, I run the script with 'trace'.因为我想知道问题到底出在哪里,所以我使用“trace”运行脚本。

py -m trace --trace  myscript.py

But I don't understand anything, I don't see any error... You can see the output of this 'trace' command on a text file I uploaded on GitHub:但是我什么都不懂,我没有看到任何错误...您可以在我上传到 GitHub 的文本文件上看到此“跟踪”命令的 output:

https://github.com/gauthierbuttez/public/blob/master/trace-log.txt https://github.com/gauthierbuttez/public/blob/master/trace-log.txt

Does anyone have any idea how can I pass the "lock" to my concurrent.futures.ProcessPoolExecutor()?有谁知道如何将“锁”传递给我的 concurrent.futures.ProcessPoolExecutor()? And is it a good idea to do that?这样做是个好主意吗?

Thanks.谢谢。

May this help you...愿这能帮助你...

    m = multiprocessing.Manager()
    lock = m.Lock()

    def run_smartphone(p_udid, lock): 
        # further code

    list_smartphones_connected = [41492968379078, 53519716736397] 
    with concurrent.futures.ProcessPoolExecutor() as executor: 
        try: 
            multiprocesses = executor.map(run_smartphone, list_smartphones_connected, [lock]*len(list_smartphones_connected)) 
            for function_return_value in multiprocesses:
                print(function_return_value)

        except ValueError: 
            print(("Error multiprocesses"))

From the docs for map():来自 map() 的文档

If a func call raises an exception, then that exception will be raised when its value is retrieved from the iterator.如果 func 调用引发异常,则在从迭代器中检索其值时将引发该异常。

In other words, you probably have to actually use the return value of run_smartphone:换句话说,您可能必须实际使用 run_smartphone 的返回值:

m = multiprocessing.Manager()
lock = m.Lock()
list_arguments_smartphones = []

list_smartphones_connected = [41492968379078, 53519716736397]
for smartphone_connected in list_smartphones_connected:        
    list_arguments_smartphones.append([smartphone_connected, lock])

with concurrent.futures.ProcessPoolExecutor() as executor:
    try:
        multiprocesses = executor.map(mymodules.run_smartphone, list_arguments_smartphones)

        for function_return_value in multiprocesses:
            print(function_return_value)
            # or do something with the value, like insert into a db

    except ValueError:
        print(("Error multiprocesses"))

But if you are having trouble even passing a lock to your function, and you haven't bothered reading the docs then I would suggest you restructure your code so that run_smartphone only reads from the database (shouldn't require a lock) and you write to the db in the for loop (doesn't require a lock).但是,如果您甚至无法将锁传递给您的 function,并且您没有费心阅读文档,那么我建议您重组您的代码,以便 run_smartphone 仅从数据库中读取(不需要锁)然后您编写到 for 循环中的数据库(不需要锁)。 Otherwise, you're going to get yourself into a deadlock quagmire.否则,你会让自己陷入僵局的泥潭。

暂无
暂无

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

相关问题 如何将 Popen 对象传递给 concurrent.futures.ProcessPoolExecutor - How to pass Popen objects to concurrent.futures.ProcessPoolExecutor 将带有对象的 function 传递到 concurrent.futures.ProcessPoolExecutor()? - Pass function with objects into concurrent.futures.ProcessPoolExecutor()? 如何监控python的concurrent.futures.ProcessPoolExecutor? - How to monitor python's concurrent.futures.ProcessPoolExecutor? concurrent.futures.ProcessPoolExecutor() 中的共享变量 python - Shared variable in concurrent.futures.ProcessPoolExecutor() python 如何将多个参数传递给由 concurrent.futures.ProcessPoolExecutor 中的 executor.map() 迭代的函数 - How to pass several parameters to a function which is iterated by executor.map() from concurrent.futures.ProcessPoolExecutor 如何使用 concurrent.futures.ProcessPoolExecutor 在进程之间传递消息/信息 - How to pass messages/information between process using concurrent.futures.ProcessPoolExecutor python concurrent.futures.ProcessPoolExecutor:.submit()vs .map()的性能 - python concurrent.futures.ProcessPoolExecutor: Performance of .submit() vs .map() Python concurrent.futures.ProcessPoolExecutor:大量 RAM 用于大量任务 - Python concurrent.futures.ProcessPoolExecutor: Lot of RAM for large number of tasks Python 3.8 - concurrent.futures.ProcessPoolExecutor 性能及时下降 - Python 3.8 - concurrent.futures.ProcessPoolExecutor performance going down in time 如何使用 asyncio 和 concurrent.futures.ProcessPoolExecutor 在 Python 中终止长时间运行的计算(CPU 绑定任务)? - How to terminate long-running computation (CPU bound task) in Python using asyncio and concurrent.futures.ProcessPoolExecutor?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM