You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何批量将pywintypes.datetime转为numpy.datetime64适配Pandas?

处理大型Excel文件中pywintypes.datetime转Pandas DataFrame的报错问题

我使用win32com读取大型Excel文件数据,通过DataBody = tbl.DataBodyRange()获取数据元组,再转成numpy数组。但win32com返回的时间列数据为pywintypes.datetime类型,直接将数组转为Pandas DataFrame时触发错误:AttributeError: 'NoneType' object has no attribute 'total_seconds'。需要找到无需迭代的批量转换方法(避免遍历大数据),比如用np.where实现转换替换。

Python代码

import win32com.client as MyWinCOM
import numpy as np
import pandas as pd

# 打开Excel实例
xl = MyWinCOM.gencache.EnsureDispatch('Excel.Application')
xl.Visible = True
# 打开工作簿
wb = xl.Workbooks.Open('Test Excel.xlsx')
# 获取工作表对象
ws = wb.Worksheets('Sheet1')
# 获取表格对象
tbl = ws.ListObjects('Table1')
# 获取表头并转为列表
ColumnNames = tbl.HeaderRowRange()
ColumnNamesList = list(np.array(ColumnNames))

# 获取数据区域并转为numpy数组
DataBody = tbl.DataBodyRange()
DataBody_array = np.array(DataBody)

# 打印数据元组
for item in DataBody:
    print(item)
# 打印数据数组
for item in DataBody_array:
    print(item)

# 尝试转为DataFrame
Data_df = pd.DataFrame(DataBody_array, columns=ColumnNamesList)

print(Data_df)

输出结果

('a', pywintypes.datetime(2022, 6, 22, 0, 0, tzinfo=TimeZoneInfo('GMT Standard Time', True)), 1.0)
('b', pywintypes.datetime(2023, 10, 18, 0, 0, tzinfo=TimeZoneInfo('GMT Standard Time', True)), None)
('c', pywintypes.datetime(2022, 6, 21, 0, 0, tzinfo=TimeZoneInfo('GMT Standard Time', True)), 3.0)
['a'
 pywintypes.datetime(2022, 6, 22, 0, 0, tzinfo=TimeZoneInfo('GMT Standard Time', True))
 1.0]
['b'
 pywintypes.datetime(2023, 10, 18, 0, 0, tzinfo=TimeZoneInfo('GMT Standard Time', True))
 None]
['c'
 pywintypes.datetime(2022, 6, 21, 0, 0, tzinfo=TimeZoneInfo('GMT Standard Time', True))
 3.0]

报错栈

Traceback (most recent call last):
  File "***.py", line 32, in <module>
    print (Data_df)
  File "C:\Program Files\Python39\lib\site-packages\pandas\core\frame.py", line 1011, in __repr__
    return self.to_string(**repr_params)
  File "C:\Program Files\Python39\lib\site-packages\pandas\core\frame.py", line 1192, in to_string
    return fmt.DataFrameRenderer(formatter).to_string(
  File "C:\Program Files\Python39\lib\site-packages\pandas\io\formats\format.py", line 1128, in to_string
    string = string_formatter.to_string()
  File "C:\Program Files\Python39\lib\site-packages\pandas\io\formats\string.py", line 25, in to_string
    text = self._get_string_representation()
  File "C:\Program Files\Python39\lib\site-packages\pandas\io\formats\string.py", line 40, in _get_string_representation
    strcols = self._get_strcols()
  File "C:\Program Files\Python39\lib\site-packages\pandas\io\formats\string.py", line 31, in _get_strcols
    strcols = self.fmt.get_strcols()
  File "C:\Program Files\Python39\lib\site-packages\pandas\io\formats\format.py", line 611, in get_strcols
    strcols = self._get_strcols_without_index()
  File "C:\Program Files\Python39\lib\site-packages\pandas\io\formats\format.py", line 875, in _get_strcols_without_index
    fmt_values = self.format_col(i)
  File "C:\Program Files\Python39\lib\site-packages\pandas\io\formats\format.py", line 889, in format_col
    return format_array(
  File "C:\Program Files\Python39\lib\site-packages\pandas\io\formats\format.py", line 1316, in format_array
    return fmt_obj.get_result()
  File "C:\Program Files\Python39\lib\site-packages\pandas\io\formats\format.py", line 1347, in get_result
    fmt_values = self._format_strings()
  File "C:\Program Files\Python39\lib\site-packages\pandas\io\formats\format.py", line 1810, in _format_strings
    values = self.values.astype(object)
  File "C:\Program Files\Python39\lib\site-packages\pandas\core\arrays\datetimes.py", line 666, in astype
    return dtl.DatetimeLikeArrayMixin.astype(self, dtype, copy)
  File "C:\Program Files\Python39\lib\site-packages\pandas\core\arrays\datetimelike.py", line 415, in astype
    converted = ints_to_pydatetime(
  File "pandas\_libs\tslibs\vectorized.pyx", line 158, in pandas._libs.tslibs.vectorized.ints_to_pydatetime
  File "pandas\_libs\tslibs\timezones.pyx", line 266, in pandas._libs.tslibs.timezones.get_dst_info
AttributeError: 'NoneType' object has no attribute 'total_seconds'

解决方案

报错原因是pywintypes.datetime附带的TimeZoneInfo无法被Pandas正确解析,导致内部处理时出现空值调用total_seconds()的情况。以下是几种批量转换方法:

1. 使用numpy.vectorize批量转换

通过向量化函数批量处理整个数组,避免手动遍历:

import pywintypes

def convert_pywintime(dt):
    if isinstance(dt, pywintypes.datetime):
        # 转为ISO格式字符串再转numpy.datetime64
        return np.datetime64(dt.isoformat())
    return dt

# 生成向量化转换函数
vectorized_convert = np.vectorize(convert_pywintime)
# 转换数组
DataBody_array_converted = vectorized_convert(DataBody_array)
# 生成DataFrame
Data_df = pd.DataFrame(DataBody_array_converted, columns=ColumnNamesList)

2. 针对时间列单独处理(更高效)

如果已知时间列的索引,直接对该列批量转换,减少不必要的计算:

import pywintypes

# 假设第二列是时间列(索引为1)
time_col_idx = 1
# 批量转换时间列元素
DataBody_array[:, time_col_idx] = np.array([
    np.datetime64(dt.isoformat()) if isinstance(dt, pywintypes.datetime) else dt 
    for dt in DataBody_array[:, time_col_idx]
])
# 生成DataFrame
Data_df = pd.DataFrame(DataBody_array, columns=ColumnNamesList)

3. 利用Pandas内置函数转换

先创建DataFrame,再对时间列进行转换:

# 先创建DataFrame
Data_df = pd.DataFrame(DataBody_array, columns=ColumnNamesList)
# 指定时间列名称,用to_datetime自动转换
time_col_name = "你的时间列名称"
Data_df[time_col_name] = pd.to_datetime(Data_df[time_col_name], errors="ignore")

内容的提问来源于stack exchange,提问作者Radical Edward

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 01:20:02