GVKun编程网logo

Python多重处理模块的.join()方法到底在做什么?(python 多层try)

4

如果您想了解Python多重处理模块的.join的相关知识,那么本文是一篇不可错过的文章,我们将对方法到底在做什么?进行全面详尽的解释,并且为您提供关于.join()方法到底是做什么的?、Activi

如果您想了解Python多重处理模块的.join的相关知识,那么本文是一篇不可错过的文章,我们将对方法到底在做什么?进行全面详尽的解释,并且为您提供关于.join() 方法到底是做什么的?、Activity.finish() 方法到底在做什么?、Python-.join()方法到底做什么?、Python多处理模块的有价值的信息。

本文目录一览:

Python多重处理模块的.join()方法到底在做什么?(python 多层try)

Python多重处理模块的.join()方法到底在做什么?(python 多层try)

从PMOTW文章中了解Python多重处理,并且希望对方法的确切作用进行一些说明。join()

在2008年的旧教程中,它指出,没有p.join()以下代码中的调用,“子进程将处于空闲状态而不会终止,成为必须手动杀死的僵尸”。

from multiprocessing import Processdef say_hello(name=''world''):    print "Hello, %s" % namep = Process(target=say_hello)p.start()p.join()

我添加的打印输出PID,以及一个time.sleep测试,并就我所知道的,在自己的进程终止:

from multiprocessing import Processimport sysimport timedef say_hello(name=''world''):    print "Hello, %s" % name    print ''Starting:'', p.name, p.pid    sys.stdout.flush()    print ''Exiting :'', p.name, p.pid    sys.stdout.flush()    time.sleep(20)p = Process(target=say_hello)p.start()# no p.join()

20秒内:

936 ttys000    0:00.05 /Library/Frameworks/Python.framework/Versions/2.7/Reso938 ttys000    0:00.00 /Library/Frameworks/Python.framework/Versions/2.7/Reso947 ttys001    0:00.13 -bash

20秒后:

947 ttys001    0:00.13 -bash

行为与p.join()添加回文件末尾的行为相同。每周Python模块提供了非常易读的模块解释;
“要等到进程完成工作并退出后,请使用join()方法。”,但看来至少OS X仍在这样做。

我也想知道该方法的名称。该.join()方法在此处串联吗?它是在连接过程的结尾吗?还是只是与Python的本地.join()方法共享一个名称?

答案1

小编典典

join()threading或一起使用时,该方法multiprocessing与之无关str.join()-实际上没有将任何东西串联在一起。相反,它仅表示“等待此[线程/进程]完成”。join之所以使用该名称,是因为该multiprocessing模块的API看起来类似于该threading模块的API,并且该threading模块join用于其Thread对象。join在许多编程语言中,使用该术语表示“等待线程完成”是很常见的,因此Python也采用了它。

现在,您看到有和没有调用都延迟20秒的原因join()是因为默认情况下,当主进程准备退出时,它将隐式调用join()所有正在运行的multiprocessing.Process实例。在multiprocessing文档中并未对此进行明确说明,但在“编程指南”部分中进行了提及:

还请记住,非守护进程将自动加入。

您可以通过设置覆盖此行为daemon上的标志ProcessTrue之前,要启动的过程:

p = Process(target=say_hello)p.daemon = Truep.start()# Both parent and child will exit here, since the main process has completed.

如果这样做,则子进程将在主进程完成后立即终止:

守护程序

进程的守护程序标志,一个布尔值。必须在调用start()之前进行设置。

初始值是从创建过程继承的。

进程退出时,它将尝试终止其所有守护程序子进程。

.join() 方法到底是做什么的?

.join() 方法到底是做什么的?

我对 Python 还是很陌生,并且完全混淆了.join()我所读过的连接字符串的首选方法。

我试过了:

strid = repr(595)
print array.array('c',random.sample(string.ascii_letters,20 - len(strid)))
    .tostring().join(strid)

并得到类似的东西:

5wlfgALGbXOahekxSs9wlfgALGbXOahekxSs5

为什么它会这样工作?不应该595只是自动附加吗?

Activity.finish() 方法到底在做什么?

Activity.finish() 方法到底在做什么?

我正在开发android应用程序一段时间,并关注了很多关于活动生命周期和应用程序生命周期的帖子。

我知道Activity.finish()在某处调用方法Activity.onDestroy(),并从堆栈中删除活动,我猜它以某种方式指向操作系统和垃圾收集器,他可以“做他的伎俩”并在发现它的好时机释放内存所以....

这让我对这个方法到底做了什么感到有点困惑finish()

有没有机会我会打电话finish()onDestroy()不会被打电话?

答案1

小编典典

当调用 finish() 一个活动时,该方法 onDestroy() 被执行。此方法可以执行以下操作:

  1. 关闭活动正在管理的任何对话框。
  2. 关闭活动正在管理的所有游标。
  3. 关闭任何打开的搜索对话框

另外, onDestroy()
不是析构函数。它实际上并没有破坏对象。它只是一种基于某种状态调用的方法。因此,在超类运行并返回之后,您的实例仍然存在并且非常好*
onDestroy()。Android
保留进程以防用户想要重新启动应用程序,这使得启动阶段更快。该进程将不会做任何事情,如果需要回收内存,该进程将被杀死

Python-.join()方法到底做什么?

Python-.join()方法到底做什么?

如何解决Python-.join()方法到底做什么??

仔细查看你的输出:

5wlfgalGbXOahekxSs9wlfgalGbXOahekxSs5
^    
     ^                 ^

我突出显示了原始字符串的“ 5”,“ 9”,“ 5”。Python的join()方法是一个字符串的方法,而且占据了名单的事情,加入以字符串。一个简单的示例可能有助于解释:

>>> ",".join(["a", "b", "c"])
''a,b,c''

在给定列表的每个元素之间插入“,”。在你的情况下,你的“列表”是字符串表示形式“ 595”,它被视为列表[“ 5”,“ 9”,“ 5”]

看来你要寻找的是+:

print array.array(''c'', random.sample(string.ascii_letters, 20 - len(strid)))
.tostring() + strid

解决方法

我对Python来说还很陌生,并且完全不.join()理解所读内容是连接字符串的首选方法。

我试过了:

strid = repr(595)
print array.array(''c'',random.sample(string.ascii_letters,20 - len(strid)))
    .tostring().join(strid)

并得到类似:

5wlfgALGbXOahekxSs9wlfgALGbXOahekxSs5

为什么会这样工作?难道不595应该自动追加吗?

Python多处理模块

Python多处理模块

编辑:更新了环境信息(参见第一部分)

环境

我正在使用Python 2.7

Ubuntu 16.04

问题

我有一个应用程序,我已经简化为一个三阶段的过程:

>从多个数据源(HTTP请求,系统信息等)收集数据
>根据此数据计算指标
>以各种格式输出这些指标

在进入下一阶段之前,每个阶段都必须完成,但是每个阶段都包含多个可以并行运行的子任务(我可以发送3个HTTP请求并在等待它们返回时读取系统日志)

我已经将阶段划分为模块,将子任务划分为子模块,因此我的项目层次结构如下:

+ datasources
|-- __init__.py
|-- data_one.py
|-- data_two.py
|-- data_three.py
+ metrics
|-- __init__.py
|-- metric_one.py
|-- metric_two.py
+ outputs
|-- output_one.py
|-- output_two.py
- app.py

app.py看起来大致如此(伪代码简洁):

import datasources
import metrics
import outputs

for datasource in dir(datasources):
    datasource.refresh()
for metric in dir(metrics):
    metric.calculate()
for output in dir(outputs):
    output.dump()

(包含dir调用的附加代码忽略系统模块,有异常处理等 – 但这是它的要点)

每个数据源子模块看起来大致如下:

data = []

def refresh():
    # Populate the "data" member somehow
    data = [1,2,3]
    return

每个度量子模块看起来大致如下:

import datasources.data_one as data_one
import datasources.data_two as data_two

data = []

def calculate():
    # Use the datasources to compute the metric
    data = [sum(x) for x in zip(data_one,data_two)]
    return

为了并行化第一阶段(数据源),我写了一些简单的东西,如下所示:

def run_thread(datasource):
    datasource.refresh()

threads = []
for datasource in dir(datasources):
    thread = threading.Thread(target=run_thread,args=(datasource))
    threads.append(thread)
    thread.start()
for thread in threads:
    thread.join()

这可以工作,然后我可以计算任何指标,并填充datasources.x.data属性

为了并行化第二阶段(度量),因为它更少依赖于I / O而更多地依赖于cpu,我觉得简单的线程实际上不会加速,我需要多处理模块才能利用多核.我写了以下内容:

def run_pool(calculate):
    calculate()

pool = multiprocessing.Pool()
pool.map(run_pool,[m.calculate for m in dir(metrics)]
pool.close()
pool.join()

这段代码运行了几秒钟(所以我认为它有效吗?)但是当我尝试时:

metrics.metric_one.data

它返回[],就像模块从未运行过一样

不知何故,通过使用多处理模块,它似乎是对线程进行限定,以便它们不再共享数据属性.我应该如何重写这一点,以便我可以并行计算每个指标,利用多个核心,但在完成后仍然可以访问数据?

解决方法

根据评论再次更新:
因为你在2.7,并且你正在处理模块而不是对象,所以你在挑选你需要的东西时遇到了问题.解决方法并不漂亮.它涉及将每个模块的名称传递给您的操作功能.我更新了部分部分,并且还更新了删除with语法.

一些东西:

首先,一般来说,多线程比线程更好.使用线程,您总是冒着处理Global Interpreter Lock的风险,这可能效率极低.如果您使用多核,这将成为一个非问题.

其次,你有正确的概念,但是通过拥有一个全局到模块的数据成员,你会让它变得奇怪.使您的源返回您感兴趣的数据,并使您的度量(和输出)将数据列表作为输入并输出结果列表.

这会将你的伪代码变成这样的东西:

app.py:

import datasources
import metrics
import outputs

pool = multiprocessing.Pool()
data_list = pool.map(lambda o: o.refresh,list(dir(datasources)))
pool.close()
pool.join()

pool = multiprocessing.Pool()
metrics_funcs = [(m,data_list) for m in dir(metrics)]
metrics_list = pool.map(lambda m: m[0].calculate(m[1]),metrics_funcs)
pool.close()
pool.join()

pool = multiprocessing.Pool()
output_funcs = [(o,data_list,metrics_list) for o in dir(outputs)]
output_list = pool.map(lambda o: o[0].dump(o[1],o[2]),output_funcs)
pool.close()
pool.join()

完成此操作后,您的数据源将如下所示:

def refresh():
    # Populate the "data" member somehow
    return [1,3]

您的指标看起来像这样:

def calculate(data_list):
    # Use the datasources to compute the metric
    return [sum(x) for x in zip(data_list)]

最后,您的输出可能如下所示:

def dump(data_list,metrics_list):
    # do whatever; you Now have all the information

删除数据“全局”并传递它使每个部分更清洁(并且更容易测试).这突出了使每件作品完全独立.正如你所看到的,我正在做的就是改变传递给map的列表中的内容,在这种情况下,我通过将它们作为元组传递并在函数中解压缩来注入所有先前的计算.当然,你不必使用lambdas.您可以单独定义每个函数,但实际上并没有太多定义.但是,如果确实定义了每个函数,则可以使用partial函数来减少传递的参数数量.我经常使用这种模式,在你更复杂的代码中,你可能需要.这是一个例子:

from functools import partial

do_dump(module_name,metrics_list):
    globals()[module_name].dump(data_list,metrics_list)

invoke = partial(do_dump,data_list=data_list,metrics_list=metrics_list)
with multiprocessing.Pool() as pool:
    output_list = pool.map(invoke,[o.__name__ for o in dir(outputs)])
    pool.close()
    pool.join()

根据评论更新:

当您使用map时,您可以保证输入的顺序与输出的顺序相匹配,即data_list [i]是运行dir(datasources)[i] .refresh()的输出.我不会将数据源模块导入指标,而是将其更改为app.py:

data_list = ...
pool.close()
pool.join()
data_map = {name: data_list[i] for i,name in enumerate(dir(datasources))}

然后将data_map传递给每个指标.然后,度量标准按名称获取它想要的数据,例如

d1 = data_map[''data_one'']
d2 = data_map[''data_two'']
return [sum(x) for x in zip([d1,d2])]

关于Python多重处理模块的.join方法到底在做什么?的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于.join() 方法到底是做什么的?、Activity.finish() 方法到底在做什么?、Python-.join()方法到底做什么?、Python多处理模块的相关信息,请在本站寻找。

本文标签: