简而言之
我将BrokenProcessPool代码并行化时遇到异常concurrent.futures.不会显示进一步的错误.我想找出错误的原因并询问如何做到这一点的想法.
完全问题
我使用concurrent.futures来并行化一些代码.
with ProcessPoolExecutor() as pool:
mapObj = pool.map(myMethod, args)
Run Code Online (Sandbox Code Playgroud)
我最终得到(并且只有)以下异常:
concurrent.futures.process.BrokenProcessPool: A child process terminated abruptly, the process pool is not usable anymore
Run Code Online (Sandbox Code Playgroud)
不幸的是,程序很复杂,只有在程序运行30分钟后才会出现错误.因此,我无法提供一个很好的最小例子.
为了找到问题的原因,我将try-except-block并行运行的方法包装起来:
def myMethod(*args):
try:
...
except Exception as e:
print(e)
Run Code Online (Sandbox Code Playgroud)
问题保持不变,并且从未输入过块.我得出结论,异常并非来自我的代码.
我的下一步是编写一个ProcessPoolExecutor原始子类的自定义类,ProcessPoolExecutor并允许我用cusomized替换一些方法.我复制并粘贴了方法的原始代码_process_worker并添加了一些print语句.
def _process_worker(call_queue, result_queue):
"""Evaluates calls from call_queue and places the results in result_queue.
...
"""
while True:
call_item = call_queue.get(block=True)
if call_item is None:
# Wake up queue management …Run Code Online (Sandbox Code Playgroud) 我用PyQt4编写了一个很小的python程序.现在,我想使用cx_Freeze创建一个独立的应用程序.一切正常 - cx_Freeze自动包含所有必要的模块; 结果exe工作.
唯一的问题是cx_Freeze将大量不需要的模块打包到独立模块中.即使我只使用QtCore和QtGui,也包括sqlite3,QtNetwork或QtScript等模块.令人惊讶的是,我在结果文件夹中找到了PyQt5 dll.在我看来,好像cx_Freeze使用我安装的所有PyQt包.结果是一个200Mb的程序 - 虽然我只写了一个小脚本.
我该如何防止这种行为?
我使用以下setup.py:
import sys
from cx_Freeze import setup, Executable
setup(
name="MyProgram",
version="0.1",
description="MyDescription",
executables=[Executable("MyProgram.py", base = "Win32GUI")],
)
Run Code Online (Sandbox Code Playgroud)
我试着明确地排除了一些软件包(虽然排除所有未使用的Qt模块非常麻烦)添加以下代码:
build_exe_options = {"excludes": ["tkinter", "PyQt4.sqlite3",
"PyQt4.QtOpenGL4", "PyQt4.QtSql"]}
Run Code Online (Sandbox Code Playgroud)
但上层模块仍在使用.我也试过了
build_exe_options = {"excludes": ["tkinter", "PyQt4.sqlite3",
"QtOpenGL4", "QtSql"]}
Run Code Online (Sandbox Code Playgroud)
结果相同.
除了无用的Qt包之外,我还找到了名为"imageformats","tcl"和"tk"的不需要的文件夹.如何仅包含所需文件以使独立文件夹和安装程序尽可能小?
我用谷歌搜索了这个问题几个小时,但只发现这个帖子没有帮助我.
我在Windows 8上运行python 3.4.2 amd64.
我很高兴每个解决方案都能以合理的尺寸"独立"地获得所需的结果.我也尝试了pyqtdeploy但遇到了错误:QT中的未知模块(但这是一个不同的问题).
我正在使用两个模块.一个是由uic创建的GUI类,"MyProgramGUIPreset".在此文件中有以下导入命令:
from PyQt4 import QtCore, QtGui
from matplotlibwidget import MatplotlibWidget
Run Code Online (Sandbox Code Playgroud)
在主模块中,我执行以下导入:
import MyProgramGUIPreset
import numpy as np
from PyQt4.QtGui import QApplication, QMainWindow, QMessageBox
import sys …Run Code Online (Sandbox Code Playgroud) 简而言之
我想同时更改复杂的python对象,每个对象只由一个进程处理.我怎么能这样做(效率最高)?实施某种酸洗支持会有帮助吗?这会有效吗?
完整的问题
我有一个python数据结构ArrayDict,基本上由一个numpy数组和一个字典组成,并将任意索引映射到数组中的行.在我的例子中,所有键都是整数.
a = ArrayDict()
a[1234] = 12.5
a[10] = 3
print(a[1234]) #12.5
print(a[10]) # 3.0
print(a[1234] == a.array[a.indexDict[1234]]) #true
Run Code Online (Sandbox Code Playgroud)
现在我有多个这样的ArrayDicts并希望填写它们myMethod(arrayDict, params).由于myMethod价格昂贵,我想并行运行它.请注意,myMethod可能会添加许多行arrayDict.每个过程都会改变自己的过程ArrayDict.我不需要并发访问ArrayDicts.
在myMethod,我更改了条目arrayDict(即,我更改了内部numpy数组),我添加了条目arrayDict(也就是说,我向字典添加另一个索引并在内部数组中写入一个新值).最终,我希望能够在arrayDict内部numpy阵列变得太小时进行交换.这不会经常发生,如果没有更好的解决方案,我可以在程序的非并行部分执行此操作.即使没有阵列交换,我自己的尝试也没有成功.
我花了几天时间研究共享内存和python的多处理模块.由于我最终将在linux上工作,因此任务似乎相当简单:系统调用fork()允许有效地处理参数的副本.我的想法是ArrayDict在自己的进程中更改每个,返回对象的更改版本,并覆盖原始对象.为了节省内存并保存复制工作,我还使用了sharedmem数组来存储数据ArrayDict.我知道字典必须仍然被复制.
from sharedmem import sharedmem
import numpy as np
n = ... # length of …Run Code Online (Sandbox Code Playgroud) 我想用python解决一个线性程序。变量的数量(从现在开始我称之为 N)非常大(~50000),为了以scipy.optimize.linprog需要的方式表述问题,我必须构造两个 N x N 矩阵(A及B以下)。LP 可以写成
minimize: c.x
subject to:
A.x <= a
B.x = b
x_i >= 0 for all i in {0, ..., n}
Run Code Online (Sandbox Code Playgroud)
其中.表示点积a,而b、 和c是长度为 N 的向量。
我的经验是构建如此大的矩阵(A并且B都有大约 50000x50000 = 25*10^8 个条目)会带来一些问题:如果硬件不是很强大,NumPy 可能根本拒绝构建如此大的矩阵(参见例如使用 Python 和 NumPy 的非常大的矩阵),即使 NumPy 创建矩阵没有问题,也存在巨大的性能问题。对于 NumPy 必须处理的大量数据,这是很自然的。
然而,尽管我的线性程序带有 N 个变量,但我使用的矩阵非常稀疏。其中一个只有第一行的条目,另一个只有前 M 行,其中 M < N/2。当然,我想利用这个事实。
据我所知(例如,尝试使用稀疏矩阵和失败来解决 Scipy 优化问题),scipy.optimize.linprog不适用于稀疏矩阵。因此,我有以下问题: …
我想将我的python版本从3.5升级到3.6.由于我使用的是WinPython,我已经下载并安装了最新版本,就像我之前使用的是3.5版一样.
但是,如果我使用版本3.6,ModuleNotFoundError每当我导入自创模块时,我都会得到一个.一个最小的例子:我创建了一个t1.py只包含一个pass语句的文件和一个t2.py包含以下代码的文件:
import t1
print("done")
Run Code Online (Sandbox Code Playgroud)
两个文件都在同一个文件夹中D:\MyProject\src.现在当我用python 3.5运行文件时,一切正常:
'C:\Program Files\WinPython-64bit-3.5.1.2\python-3.5.1.amd64\python.exe' D:\MyProject\src\t2.py
done
Run Code Online (Sandbox Code Playgroud)
但是,使用python 3.6我得到了
'C:\Program Files\WinPython-64bit-3.6.0.1Qt5\python-3.6.0.amd64\python.exe' D:\MyProject\src\t2.py
Traceback (most recent call last):
File "D:\MyProject\src\t2.py", line 6, in <module>
import t1
ModuleNotFoundError: No module named 't1'
Run Code Online (Sandbox Code Playgroud)
我没有想到问题可能是什么,并会欣赏新的灵感.
我的python程序占用了比预期更多的内存或由内存分析工具返回.我需要一个策略来查找内存泄漏并修复它.
我在64位Linux机器上运行python3脚本.几乎所有代码都捆绑在一个对象中:
obj = MyObject(*myArguments)
result = obj.doSomething()
print(result)
Run Code Online (Sandbox Code Playgroud)
在创建过程中obj,程序会读取大小为ca.的文本文件.100MB.由于我以多种方式保存信息,我希望整个对象占用几个hundret MB内存.
实际上,用asizeof.asized(obj)包pympler测量它的大小会返回大约123MB.但是,top告诉我我的程序占用大约1GB的内存.
我知道方法中的局部变量会占用更多的RAM.但是,查看我的代码,我发现这些局部变量都不会那么大.我asizeof.asized再次使用双重检查.
我不担心脚本需要1GB的内存.但是,我并行执行了一些方法(在12个方面):
class MyObject()
def doSomething(arg):
# do something
def myParallelMethod(args)
with sharedmem.MapReduce() as pool:
result = pool.map(self.doSomething, args)
return result
Run Code Online (Sandbox Code Playgroud)
这使得总内存使用量变为8GB,即使我将所有大对象放在共享内存中:
self.myLargeNumPyArray = sharedmem.copy(self.myLargeNumPyArray)
Run Code Online (Sandbox Code Playgroud)
我向测试程序保证内存真的是共享的.
检查asizeof,我在每个子进程中获得了
asizeof.asized(self) 是1MB(即比"原始"对象小得多 - 可能是由于共享内存,不计算两倍)asizeof.asized(myOneAndOnlyBigLocalVariable) 是230MB.总而言之,我的程序应该占用不超过123MB + 12*230MB = 2.8GB << 8GB.那么,为什么程序需要这么多内存呢?
一种解释可能是当程序并行运行时,我的对象中存在一些被隐藏的部分(垃圾?).
有没有人知道找出内存泄漏的策略?我该怎么办呢?
我已阅读有关内存分析多个线程,例如剖析内存在Python 3,是否有工作存储器剖析了Python3, …
我已经使用python的cProfile模块分析了我的python代码,并获得了以下结果:
ncalls tottime percall cumtime percall filename:lineno(function)
13937860 96351.331 0.007 96351.331 0.007 {method 'poll' of 'select.poll' objects}
13930480 201.012 0.000 201.012 0.000 {built-in method posix.read}
13937860 180.207 0.000 97129.916 0.007 connection.py:897(wait)
13937860 118.066 0.000 96493.283 0.007 selectors.py:356(select)
6968925 86.243 0.000 97360.129 0.014 queues.py:91(get)
13937860 76.067 0.000 194.402 0.000 selectors.py:224(register)
13937860 64.667 0.000 97194.582 0.007 connection.py:413(_poll)
13930480 64.365 0.000 279.040 0.000 connection.py:374(_recv)
31163538/17167548 64.083 0.000 106.596 0.000 records.py:230(__getattribute__)
13937860 57.454 0.000 264.845 0.000 selectors.py:341(register)
...
Run Code Online (Sandbox Code Playgroud)
显然,我的程序将大部分运行时间都花在上method 'poll' of …
假设我们得到两个2D numpy数组,a并且b行数相同。进一步假设我们知道,每一行i的a和b具有共同至多有一个元素,但该元素可能会出现多次。我们如何才能最有效地找到这个元素?
一个例子:
import numpy as np
a = np.array([[1, 2, 3],
[2, 5, 2],
[5, 4, 4],
[2, 1, 3]])
b = np.array([[4, 5],
[3, 2],
[1, 5],
[0, 5]])
desiredResult = np.array([[np.nan],
[2],
[5],
[np.nan]])
Run Code Online (Sandbox Code Playgroud)
通过intersect1d沿第一个轴进行应用,很容易提出一个有力的实现:
from intertools import starmap
desiredResult = np.array(list(starmap(np.intersect1d, zip(a, b))))
Run Code Online (Sandbox Code Playgroud)
显然,使用python的内置set操作甚至更快。将结果转换为所需形式很容易。
但是,我需要一个尽可能高效的实现。因此,我不喜欢starmap,因为我想它需要为每行进行python调用。我想要一个纯粹的向量化选项,并且很高兴,即使这甚至利用了我们的额外知识,即每行最多有一个公共值。
有谁知道如何加快任务速度并更优雅地实施解决方案?使用C代码或cython是可以的,但是编码工作不会太多。
我想在 matplotlib 中创建一个具有指定大小的绘图,例如
plt.figure(figsize=(3, 3))
Run Code Online (Sandbox Code Playgroud)
我向图中添加一些内容并绘制颜色条
plt.colorbar()
Run Code Online (Sandbox Code Playgroud)
现在,整个图形的原始尺寸(3x3 英寸)保持不变,但绘图的宽度(实际内容)减小,以适合 3x3 英寸窗口中的绘图和颜色条。
添加颜色条时如何保持绘图区域的宽度固定并根据需要调整整个图形的大小?
简而言之
我尝试编译一个名为extension2cimportsextension从自创建包中导入文件的 cython 扩展。构建时extension2,我收到了extension.pxd未找到的错误,尽管此文件正好位于指定的路径中。
细节
我正在构建两个涉及 cython 的包,一个包A和一个B依赖于A. A是命名空间包的子包nsp。也就是说,文件夹结构如下所示:
??? nsp
? ??? A
| ??? extension.pxd
| ??? extension.pyx
? ??? __init__.py
??? setup.py
Run Code Online (Sandbox Code Playgroud)
在这里,setup.py内容如下:
from setuptools import setup
from setuptools.extension import Extension
# factory function
def my_build_ext(pars):
# import delayed:
from setuptools.command.build_ext import build_ext as _build_ext
# include_dirs adjusted:
class build_ext(_build_ext):
def finalize_options(self):
_build_ext.finalize_options(self)
# Prevent numpy from thinking …Run Code Online (Sandbox Code Playgroud) 我有一些相互继承的类。所有类都包含相同的方法(让我们称之为mymethod),由此子类覆盖基类方法。我想mymethod使用sphinx为所有类生成文档。
假设mymethod接受一个论点myargument。此参数对于基方法和继承方法具有相同的类型和含义。为了尽量减少冗余,我myargument只想为基类编写文档,并将文档插入子方法的文档中。也就是说,我不想只对基类进行简单的引用,而是在生成文档时动态插入文本。
这能做到吗?如何?
请在下面找到一些说明问题的代码。
class BaseClass
def mymethod(myargument):
"""This does something
Params
------
myargument : int
Description of the argument
"""
[...]
class MyClass1(BaseClass):
def mymethod(myargument):
"""This does something
Params
------
[here I would like to insert in the description of ``myargument`` from ``BaseClass.mymethod``]
"""
BaseClass.mymethod(myargument)
[...]
class MyClass2(BaseClass):
def mymethod(myargument, argument2):
"""This does something
Params
------
[here I would like to insert in …Run Code Online (Sandbox Code Playgroud) 我必须从许多进程中访问一组大型且不可选取的 python 对象。因此,我想确保这些对象没有被完全复制。
根据这篇文章和这篇文章中的评论,对象不会被复制(在 UNIX 系统上),除非它们被更改。然而,引用一个对象将会改变它的引用计数,而引用计数又会被复制。
到目前为止这是正确的吗?由于我担心的是大型对象的大小,因此如果复制这些对象的小部分,我不会有问题。
为了确保我正确理解所有内容并且不会发生意外情况,我实现了一个小测试程序:
from multiprocessing import Pool
def f(arg):
print(l, id(l), object.__repr__(l))
l[arg] = -1
print(l, id(l), object.__repr__(l))
def test(n):
global l
l = list(range(n))
with Pool() as pool:
pool.map(f, range(n))
print(l, id(l), object.__repr__(l))
if __name__ == '__main__':
test(5)
Run Code Online (Sandbox Code Playgroud)
在 的第一行中f,我希望id(l)在所有函数调用中返回相同的数字,因为列表在检查之前没有更改id。
另一方面,在 的第三行中f,id(l)应该在每个方法调用中返回不同的数字,因为列表在第二行中发生了更改。
然而,程序的输出让我感到困惑。
[0, 1, 2, 3, 4] 139778408436488 <list object at 0x7f20b261d308>
[-1, 1, 2, 3, 4] 139778408436488 <list …Run Code Online (Sandbox Code Playgroud) 我正在使用 Python 3.8 的新shared_memory模块并且无法在不终止使用它的进程的情况下释放共享内存。
在创建和使用shm共享内存块后,我shm.close()在所有进程中关闭它,最后shm.unlink在主进程中释放它。但是,资源监视器显示内存在程序终止之前不会被释放。这对我来说是一个严重的问题,因为我的程序需要运行很长时间。可以使用以下程序在 Windows/Python 3.8 上重现该问题:
from multiprocessing import shared_memory, Pool
from itertools import repeat
from time import sleep
def fun(dummy, name):
# access shared memory
shm = shared_memory.SharedMemory(name=name)
# do work
sleep(1)
# release shared memory
shm.close()
return dummy
def meta_fun(pool):
# create shared array
arr = shared_memory.SharedMemory(create=True, size=500000000)
# compute result
result = sum(pool.starmap(fun, zip(range(10), repeat(arr.name))))
# release and free memory
arr.close()
arr.unlink()
return result
if …Run Code Online (Sandbox Code Playgroud) python ×12
fork ×2
profiling ×2
colorbar ×1
cx-freeze ×1
cython ×1
cythonize ×1
debugging ×1
deployment ×1
figure ×1
import ×1
inheritance ×1
matplotlib ×1
memory ×1
memory-leaks ×1
methods ×1
numpy ×1
pickle ×1
pyqt ×1
python-3.6 ×1
scipy ×1
windows ×1