【发布时间】:2020-07-29 19:59:42
【问题描述】:
我目前正在开发一个需要 Python C-API 的项目
所以我在 C 端创建了一个类,并从它继承了 python 端。
未来的 C 函数之一应返回 None 或 dict。
功能:
static PyObject* handle_data(BaseClassObject* self){
struct data *data;
static int counter= 0;
// get next data from queue
if ((data= data_queue_pop(self->data_queue))) {
// TODO: build a Python dict from data and return it
free_data(data);
counter++;
}
return Py_None;
}
在这个开发阶段,函数data_queue_pop什么都不返回,因此这段代码总是到达return Py_None;
在 Python 方面,我有流动的类:
from concurrent.futures import ThreadPoolExecutor
from threading import Thread
from time import sleep
from utils.logger import getLogger
logger = getLogger(__name__)
try:
from samplelib import BaseClass
except ImportError:
from uploadlib import BaseClass
class SomeClass(BaseClass):
def __init__(self, args):
super().__init__()
self.log = logger.getChild(self.__class__.__name__)
self.version = self.version.rstrip() # self.version is intilaied in the C side
self.args = args
self.wait = True
self._pool = ThreadPoolExecutor(max_workers=1)
self.worker = None
def __enter__(self):
self.log.info(f"set worker")
# self.worker = Thread(target=self._handle_data)
self.worker = self._pool.submit(self._handle_data)
# self.log.info(f"worker start")
# self.worker.start()
self.log.info(f"return self")
return self
def __exit__(self, a, b, c):
self.log.info(f"exit {self.__class__.__name__}")
# self.log.info('stop thread')
self.wait = False
if self.worker:
self.log.info('wait for thread to stop')
self.log.info(self.worker.cancel())
# self.worker.join()
self.log.info('exiting...')
def _handle_data(self):
self.log.info(f"thread started")
while self.wait:
data = self.handle_data()
if data:
self.log.warning(data)
self.log.info(f"thread stopped")
def main():
args = _parse_args()
with SomeClass(args) as e:
sleep(2)
print(e.version)
# e.wait = False
if __name__ == "__main__":
main()
不管我尝试做什么,我都会收到以下错误:
Fatal Python error: deallocating None
Current thread 0x00007f8c37b17700 (most recent call first):
File "/home/ramih/SomeClass-automation/utils/some_module.py", line 50 in _handle_alert
File "/usr/lib/python3.6/concurrent/futures/thread.py", line 56 in run
File "/usr/lib/python3.6/concurrent/futures/thread.py", line 69 in _worker
File "/usr/lib/python3.6/threading.py", line 864 in run
File "/usr/lib/python3.6/threading.py", line 916 in _bootstrap_inner
File "/usr/lib/python3.6/threading.py", line 884 in _bootstrap
Thread 0x00007f8c3aedc740 (most recent call first):
File "./test.py", line 124 in main
File "./test.py", line 130 in <module>
Aborted (core dumped)
为什么会这样?!
如何调试它?!
我可以让线程更安全吗?!
谢谢。
【问题讨论】:
-
这是某个地方的引用计数错误 - 您以某种方式设法减少引用
None的次数比增加它的次数多,这意味着全局None对象已被破坏。不幸的是,您的示例与minimal reproducible example 相去甚远,因此很难提供更多细节。 -
@DavidW 也许我的示例远不及最小的可重现示例,但您的回复帮助我找到了解决方案,我只是将
return Py_None;替换为Py_RETURN_NONE;,问题就解决了。两行之间的区别在于宏Py_RETURN_NONE还增加了 None 对象的引用,因此,非常感谢 :) -
很高兴它有帮助!听起来不错。
标签: python-3.x multithreading python-c-api