我正在努力解决一个非常奇怪的Python行为,我无法摆脱它。
我创建了一个Python外部库,我从我的主python脚本中导入。该库接收一个巨大的(最多50MB)JSON文本文档,分为几个部分。我需要解析这些部分中的每一部分并使用正则表达式提取数据。
为了加快这个过程,并了解Python不能在多核CPU上扩展的限制,我决定使用多处理库来创建与物理CPU上可用核心一样多的进程。
库将主JSON拆分为多个部分,并初始化不同的multiprocessing.Process实例,将特定文本部分传递给每个进程。
我是这样做的:
p_one = multiprocessing.Process(
name=name,
target=functionOne,
args=(buffer1, id1)
)
p_one.start()
p_two = multiprocessing.Process(
name=name,
target=functionTwo,
args=(buffer2, id2)
)
p_two start()
p_three = multiprocessing.Process(
name=name,
target=functionThree,
args=(buffer3, id3)
)
p_three.start()
p_four = multiprocessing.Process(
name=name,
target=functionFour,
args=(buffer4, id4)
)
p_four.start()
p_one.join()
p_two.join()
p_three.join()
p_four.join()
这通常有效,但是有时候其中一个被调用的连接会挂起并挂起整个主lib - 从而阻止我的主脚本继续运行。
子进程没有崩溃,他们使用Google re2作为正则表达式库,他们完成了解析程序。
如前所述,每次都不会发生这种情况,我会说这是非常随机的。如果我杀死整个进程并使用相同的字符串缓冲区重新启动它,那么它完全有效,所以正则表达式规则没有错,也没有挂任何东西。
我尝试使用多处理映射函数,但它最终创建了僵尸进程,因此我交换到了multiprocessing.Process。
我还检查了Pyrasite,并且阻塞的线程在连接函数上挂起。
"/usr/local/lib/python2.7/dist-packages/xxxxx/dispatcher.py", line 401, in p_domain
p_two.join()
File "/usr/lib/python2.7/multiprocessing/process.py", line 145, in join
res = self._popen.wait(timeout)
File "/usr/lib/python2.7/multiprocessing/forking.py", line 154, in wait
return self.poll(0)
File "/usr/lib/python2.7/multiprocessing/forking.py", line 135, in poll
pid, sts = os.waitpid(self.pid, flag)
请您有任何提示/建议/某些内容可以帮助我理解为什么会发生这种情况以及如何解决这个问题?
非常感谢!
*加法*
这是在subprocess.Process()子项
中调用的一段代码的示例def check_domains(buf, id):
warnings = []
related_list = []
strings, _ = parse_json_string(buf)
for string in strings:
_current_result = _check_single_domain(string)
# If no result, add a warning message
if _current_result is False:
warnings.append("String timed out in DOMAIN section.")
else:
if _current_result is not None:
related_list.append(_current_result)
related_list = list(set(related_list))
[...cut...]
def _check_single_domain(string):
global DOMAIN_RESULT
# Check string length
if len(string) > MAX_STRING_LENGTH_FOR_DOMAIN:
return None
# Check unacceptable characters inside string
for unacceptable in UNACCEPTABLE_DOMAIN_CHARACTERS:
if unacceptable in string:
return None
# Check if string contains unacceptable characters
for required in REQUIRED_DOMAIN_CHARACTERS:
if required not in string:
return None
# Try to match string against Domain regex using Thread with timeout
thread = threading.Thread(name='Thread-DOMAIN', target=_perform_regex_against_string, args=(string, ))
thread.setDaemon(True)
thread.start()
thread.join(TIMEOUT_REGEX_FOR_DOMAIN_IN_SECONDS)
# If a time out occurred, return False that meaning no result got
if thread.isAlive():
return False
if DOMAIN_RESULT is None:
return None
# Domain can not starts or ends with a dot character
if DOMAIN_RESULT.endswith(".") or DOMAIN_RESULT.startswith("."):
return None
return DOMAIN_RESULT
def _perform_regex_against_string(string):
global DOMAIN_RESULT
# Set result to default value
DOMAIN_RESULT = None
# Regex for Domains
matched = re.search(REGEX, string, re.IGNORECASE)
if matched:
DOMAIN_RESULT = ''.join(matched.groups())