一定数量的数据后Python子进程失败

时间:2016-07-30 00:12:26

标签: python multithreading pipe subprocess

我正在使用Python和Java进行一些科学计算。 Python将排列发送到要处理的Java代码。我使用带有管道数据的子进程对象进出。这个系统可以工作到大约75k permeations。那时它崩溃了。最奇怪的是,无论是否改变其他变量,它在大约75k的渗透率下是如何始终如一。

Python代码一次发送50个permeations,但更改此数字不会影响崩溃的时间。

让python代码在数据的较小部分(40k,然后40k等)上运行相关函数不会影响它何时崩溃。

将同步线程的数量从4减少到1不会影响崩溃的时间。

然而,它并没有在特定的排列中崩溃,只有大约75k(可能是70k,可能是81k等)。

我完全神秘化了。 这是抛出的错误:

[1:84150]  //Thread 1, permutation #84150 
Number of threads active 2
("Failure","Failure")
Traceback (most recent call last):
File "D:\TMD Projects\BE9\BE9_RestrictHB_2A_Fine\TMD_7.28.16.py", line 836, in run
returnedDataTuple = p.communicate(sentData.encode())
File "C:\Python34\lib\subprocess.py", line 959, in communicate
stdout, stderr = self._communicate(input, endtime, timeout)
File "C:\Python34\lib\subprocess.py", line 1190, in _communicate
self.stderr_thread.start()
File "C:\Python34\lib\threading.py", line 851, in start
_start_new_thread(self._bootstrap, ())
RuntimeError: can't start new thread

这是相关代码,没有太复杂:

p = subprocess.Popen(["java","-jar","WatGenDabBatchNoTP.jar","L","6","0",str(BATCH_SIZE)], stdin=subprocess.PIPE , stdout=subprocess.PIPE, stderr=subprocess.PIPE)
returnedData = "Failure"
returnedError = "Failure"
returnedTuple = ("Failure","Failure")
try:
   returnedTuple = p.communicate(sentData.encode())
   returnedData = returnedTuple[0].decode('utf-8')
   returnedError = returnedTuple[1].decode('utf-8')
except:
   PRINT("["+str(me.thread)+":"+str(number)+"]")
   PRINT("Number of threads active "+str(threading.activeCount()))
   PRINT(str(backTuple))
   PRINT(traceback.format_exc())
finally:
   #p.stdout.flush() //Flushing buffers throws an error
   #p.stdin.flush()
   #p.stderr.flush()
   p.terminate() //Terminating process doesn't help
   p.kill()

上面的代码是循环的一部分。它在每次循环运行时发送BATCH_SIZE排列,并在达到75-85k时崩溃。 它运行在Windows 7和Python 3.4.2

1 个答案:

答案 0 :(得分:2)

有些事情要尝试:

  1. 将BATCH_SIZE更改为非常小的值。该程序是否仍然崩溃?程序在循环中的迭代次数与以前相同,是否会崩溃,或者在处理完相同数量的记录后是否崩溃?
  2. 我怀疑你在每次迭代时都泄漏了一个线程。如果是这种情况,即使BATCH_SIZE是一个小数字,程序也应该在循环相同的迭代次数后用完线程。

    另一方面,问题可能与循环处理的记录总数有关。改变BATCH_SIZE将有助于确定 如果是这种情况。

    1. 尝试在p.wait()块中添加finally。我会先单独尝试p.wait()(不调用p.kill()p.terminate())。

    2. 不要调用你的Java程序,而是调用一个简单的程序来打印出一些虚拟数据。如果问题仍然存在,那就会 消除Java程序是问题的一部分。

    3. 尽可能简化程序。仅使用一个处理线程。从程序的任何其他部分中删除线程/子进程的使用。不是生成排列,而是预先计算每个批次并将其保存在文件中。然后用 一个简单的for循环将它们提供给您的Java程序。这会有所帮助 确定你打电话subprocess.Popen的方式是否是罪魁祸首 或不。