我正在尝试调用使用pyspark rdd对象方法的python函数,并且非常耗时阻塞我的应用程序。 我需要以异步方式编写它,以便我的应用程序不会被阻止。 这是我想要做的实际事物的缩影版。
from concurrent.futures import Future
from pyspark import SparkContext
sc = SparkContext()
def add(a, b):
f = Future()
c = a + b
d = a*b
t = (c,d)
rdd = sc.parallelize([t])
f.set_result(rdd)
# return rdd
if __name__ == '__main__':
f1 = add(90,8)
f2 = add(8, 89)
while (not f1.done()) and (not f2.done()):
pass
print(f1.result())
print(f2.result())
我知道上面的代码不会立即生效。如何修改它,以便它可以工作?
答案 0 :(得分:0)
我认为你应该在函数中返回f:
def add(a, b):
f = Future()
c = a + b
d = a*b
t = (c,d)
rdd = sc.parallelize([t])
f.set_result(rdd)
return f
但不要忘记你的rdd是懒惰的。没有动作,它不应该消耗那么多时间。
答案 1 :(得分:0)
使用线程模块。我刚刚完成了一个类似的项目,它就像一个魅力。
import threading
_newThread = threading.Thread(target=<yourfunctionhere>, args=(<yourfunctionargshere>), name=<nameyourthreadhere>)
_newThread.start()
以上是核心功能。下面是一个更详细的排队作业示例,将该作业(线程)添加到一行以等待轮到(使用thread.join()方法),并返回一个具有行数(线程)的响应用于处理。
_jobId = uuid.uuid4().hex
_currentjobs = []
for t in threading.enumerate():
if t._Thread__name in [<yourthreadnamehere>,<yourthreadnamehere>]:
if t.isAlive():
_currentjobs.append(t)
_newThread = threading.Thread(target=<yourfunctionhere>, args=(<yourfunctionargshere>, _currentjobs), name=<yourthreadnamehere>)
_newThread.start()
if not _currentjobs.__len__() > 0:
return app.make_response('Job Id: ' + _jobId), 200
else:
return app.make_response('Job Id: ' + _jobId + '\n' + 'There are '+ str(_currentjobs.__len__()) + ' ahead of you, and so please be patient.'), 200
并将_currentJobs作为参数传递给您的函数,此代码在开头执行:
_currentJobs = currentJobs
for j in _currentJobs:
j.join()
重要的是要注意,您的函数应包含创建SparkContext的完整逻辑,RDD /数据帧上的惰性工作,以及您希望群集执行的任何实际工作(.collect(),提交到数据库等等) 。),因为这个线程是异步的,并且有自己的范围,传输回主线程会很复杂。