我正在使用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
上答案 0 :(得分:2)
有些事情要尝试:
我怀疑你在每次迭代时都泄漏了一个线程。如果是这种情况,即使BATCH_SIZE是一个小数字,程序也应该在循环相同的迭代次数后用完线程。
另一方面,问题可能与循环处理的记录总数有关。改变BATCH_SIZE将有助于确定 如果是这种情况。
尝试在p.wait()
块中添加finally
。我会先单独尝试p.wait()
(不调用p.kill()
或p.terminate()
)。
不要调用你的Java程序,而是调用一个简单的程序来打印出一些虚拟数据。如果问题仍然存在,那就会 消除Java程序是问题的一部分。
尽可能简化程序。仅使用一个处理线程。从程序的任何其他部分中删除线程/子进程的使用。不是生成排列,而是预先计算每个批次并将其保存在文件中。然后用
一个简单的for循环将它们提供给您的Java程序。这会有所帮助
确定你打电话subprocess.Popen
的方式是否是罪魁祸首
或不。