我有一个脚本从MySQL表中检索活动“作业”列表,然后使用多处理库为每个活动作业实例化一次主脚本。我的多处理脚本有一个函数,用于检查另一个线程是否声明了某个给定的作业。它通过检查DB表中的特定列是否为NULL来完成此操作。数据库查询返回单个项元组:
def check_if_job_claimed():
#...
job_claimed = cursor.fetchone() #Returns (claim_id,) for claimed jobs, and (None,) for unclaimed jobs
if job_claimed:
print "This job has already been claimed by another thread."
return
else:
do_stuff_to_claim_the_job
当我运行此功能没有多处理部分时,声明检查工作正常。但是当我尝试并行运行作业时,声明检查将所有(无)元组读取为具有值并因此具有真实性,因此该函数假定已经声明了该作业。
我已经尝试调整多处理器使用的并发进程数,但是声明检查仍然不起作用...即使我将进程数设置为1.我也尝试过使用if语句来看看我能不能这样做:
if job_claimed == True
if job_claimed == (None,)
# etc.
虽然没有运气。
是否有人知道多处理库中的某些内容会阻止我的声明检查功能正确解释job_claimed元组?也许我的代码出了问题?
修改
我在调试模式下对job_claimed变量运行了一些真实性测试。以下是这些测试的结果:
(pdb) job_claimed
(None,)
(pdb) len(job_claimed)
1
(pdb) job_claimed == True
False
(pdb) job_claimed == False
False
(pdb) job_claimed[0]
None
(pdb) job_claimed[0] == True
False
(pdb) job_claimed[0] == False
False
(pdb) any(job_claimed)
False
(pdb) all(job_claimed)
False
(pdb) job_claimed is not True
True
(pdb) job_claimed is not False
True
修改
根据要求:
with open('Resource_File.txt', 'r') as f:
creds = eval(f.read())
connection = mysql.connector.connect(user=creds["mysql_user"],password=creds["mysql_pw"],host=creds["mysql_host"],database=creds["mysql_db"],use_pure=False,buffered=True)
def check_if_job_claimed(job_id):
cursor = connection.cursor()
thread_id_query = "SELECT Thread_Id FROM jobs WHERE Job_ID=\'{}\';".format(job_id)
cursor.execute(thread_id_query)
job_claimed = cursor.fetchone()
job_claimed = job_claimed[0]
if job_claimed:
print "This job has already been claimed by another thread. Moving on to next job..."
cursor.close()
return False
else:
thread_id = socket.gethostname()+':'+str(random.randint(0,1000))
claim_job = "UPDATE jobs SET Thread_Id = \'{}\' WHERE Job_ID = \'{}\';".format(job_id)
cursor.execute(claim_job)
connection.commit()
print "Job is now claimed"
cursor.close()
return True
def call_the_queen(dict_of_job_attributes):
if check_if_job_claimed(dict_of_job_attributes['job_id']):
instance = OM(dict_of_job_attributes) #<-- Create instance of my target class
instance.queen_bee()
#multiprocessing code
import multiprocessing as mp
if __name__ == '__main__':
active_jobs = get_active_jobs()
pool = mp.Pool(processes = 4)
pool.map(call_the_queen,active_jobs)
pool.close()
pool.join()
答案 0 :(得分:1)
任何非空元组(或列表,字符串,可迭代等)都将评估为True
。如果iterable的内容是非True,则无关紧要。要对此进行测试,您可以使用any(iterable)
或all(iterable)
来测试iterable中的任何或所有项目是否评估为True。
但是,根据您的编辑,您的问题可能是由跨多个进程使用全局连接对象引起的。
相反,每个进程都应该创建自己的连接。
def check_if_job_claimed(job_id):
connection = mysql.connector.connect(user=creds["mysql_user"],password=creds["mysql_pw"],host=creds["mysql_host"],database=creds["mysql_db"],use_pure=False,buffered=True)
您也可以尝试使用connection pooling,但我不确定这是否适用于整个流程,并且可能需要您切换到线程。
另外,我会将if __name__ == '__main__':
下的所有代码移动到一个函数中。您通常希望在使用多处理时避免污染全局命名空间,因为当python创建新进程时,它会尝试将全局状态复制到新进程。这可能导致一些奇怪的错误,因为全局变量不再共享状态(因为它们处于不同的进程中),或者在新进程中重建时,对象在序列化期间无法序列化或丢失某些信息。