QChart时序图开发仅PySide6报OverflowError的问题问询
QChartView时间序列在PySide6下触发整型溢出报错问题
问题复现
在QChartView中创建时间序列图表时,报错发生在设置X轴(axis_x)的流程中,复现代码如下:
#!/usr/bin/env python3 import sys import collections # PySide6 from PySide6.QtGui import QPainter from PySide6.QtWidgets import QWidget, QApplication, QMainWindow from PySide6.QtCore import QPointF, QDateTime, QPoint from PySide6.QtCharts import (QChartView, QLineSeries, QValueAxis, QChart, QDateTimeAxis) # PyQt5 # from PyQt5.QtGui import QPainter # from PyQt5.QtWidgets import QWidget, QApplication, QMainWindow # from PyQt5.QtCore import QPointF, QDateTime, QPoint # from PyQt5.QtChart import QChartView, QLineSeries, QValueAxis, QChart, QDateTimeAxis class VisibilityView(QChartView): def __init__(self, parent: QWidget, maxlen: int): super().__init__(parent) self.setMinimumSize(200, 200) self.setMaximumSize(600, 400) self.maxlen = maxlen self.setRenderHint(QPainter.Antialiasing) self.setMouseTracking(True) chart = QChart() chart.legend().setVisible(False) self.setChart(chart) self.chart().setTheme(QChart.ChartThemeDark) self.series = QLineSeries(name='Prevailing Visibility') chart.addSeries(self.series) axis_x = QDateTimeAxis() axis_x.setFormat('yy/MM/dd hh:mm') axis_x.setTitleText('Time') epoch = [1655168220000, 1655168230000, 1655168881000, 1655169840000, 1655169900000, 1655169960000, 1655170020000, 1655170080000, 1655170140000, 1655170200000, 1655170260000, 1655170320000, 1655170380000, 1655170500000, 1655170560000] vis_list = [20.0, 17.0, 20.0, 20.0, 19.0, 20.0, 15.0, 20.0, 20.0, 20.0, 20.0, 20.0, 17.0, 20.0, 20.0] data = [] for i in range(len(epoch)): data.append((epoch[i], vis_list[i])) self.data = collections.deque(data, maxlen=1440) left = QDateTime.fromMSecsSinceEpoch(self.data[0][0]) right = QDateTime.fromMSecsSinceEpoch(self.data[-1][0]) axis_x.setRange(left, right) chart.setAxisX(axis_x, self.series) axis_y = QValueAxis() axis_y.setRange(0, 20) axis_y.setLabelFormat('%d km') axis_y.setTitleText('Distance (km)') chart.setAxisY(axis_y, self.series) data_point = [QPointF(t, v) for t, v in self.data] self.series.append(data_point) if __name__ == '__main__': app = QApplication(sys.argv) window = QMainWindow() graph = VisibilityView(window, 1440) window.setCentralWidget(graph) window.resize(graph.maximumSize()) window.show() sys.exit(app.exec())
运行时抛出如下报错:
... File "D:\Workspace\convert_pyside\src\visibility_view.py", line 94, in __init__ data_point = [QPointF(t, v) for t, v in self.data] File "D:\Workspace\convert_pyside\src\visibility_view.py", line 94, in <listcomp> data_point = [QPointF(t, v) for t, v in self.data] OverflowError: Python int too large to convert to C long
完全相同的代码切换到PyQt5环境运行时不会触发该报错,两个运行环境的sys.maxsize取值均为9223372036854775807,完全一致。
原因说明
PySide和PyQt确实存在Qt绑定层面的内部实现差异:
- PyQt5的类型转换逻辑更宽松,构造
QPointF传入整型参数时,会直接将数值隐式转换为C++层的qreal(双精度浮点型),不会做32位长整型的长度校验,因此不会触发溢出。 - PySide6的类型绑定校验更严格,在Windows平台下,构造
QPointF传入整型参数时,会先尝试将Python整型转换为Clong类型(Windows平台C long为32位,最大值仅2147483647),示例中使用的毫秒级时间戳数值量级为10^12,远大于32位long的上限,因此触发溢出报错。sys.maxsize反映的是平台指针宽度,和C long的长度在Windows 64位平台下并不一致,因此两个环境取值相同也会出现表现差异。
解决方法
最简便的修复方式是构造QPointF时,主动将毫秒时间戳转换为浮点型,绕过PySide6的整型转C long的校验逻辑,毫秒级时间戳在双精度浮点的精确整数表示范围内,不会出现精度丢失问题。
将原报错行修改为:
data_point = [QPointF(float(t), v) for t, v in self.data]
修改后代码在PySide6环境下可正常运行,时间轴显示、曲线绘制效果与PyQt5环境完全一致。
内容的提问来源于stack exchange,提问作者Oh Jongjin
相关产品推荐
相关产品推荐

