【问题标题】:Too many open files in Windows when writing multiple HDF5 files写入多个 HDF5 文件时,Windows 中打开的文件过多
【发布时间】:2016-12-24 11:36:52
【问题描述】:

我的问题是如何在写入后无限期关闭 HDF5 文件

我正在尝试将数据保存到 HDF5 文件 - 大约有 200 个文件夹,每个文件夹包含今年每天的一些数据。

当我在 iPython 控制台中使用 pandas HDFStore 和以下代码检索和保存数据时,该函数会在一段时间后自动停止(没有错误消息)。

import pandas as pd

data = ... # in format as pd.DataFrame
# Method 1
data.to_hdf('D:/file_001/2016-01-01.h5', 'type_1')
# Method 2
with pd.HDFStore('D:/file_001/2016-01-01.h5', 'a') as hf:
    hf['type_1'] = data

当我再次尝试使用相同的脚本下载数据时,它显示:

[Errno 24] 打开的文件太多:...

有一些帖子建议在 Linux 中使用 ulimit -n 1200 来解决这个问题,但不幸的是我使用的是 Windows。

此外,我想我已经使用 with 闭包明确地关闭了文件,尤其是在 方法 2 中。为什么 iPython 仍然将这些文件视为打开的?

我的循环如下:

univ = pd.read_excel(univ_file, univ_tab)
for dt in pd.DatetimeIndex(start=start_date, end=end_date, freq='B'):
    for t in univ:
        data = download_data(t, dt)
        with pd.HDFStore(data_file, 'a') as hf:
            # Use pd.DataFrame([np.nan]) instead of pd.DataFrame() to save space
            hf[typ] = EMPTY_DF if data.shape[0] == 0 else data

【问题讨论】:

  • 这两种方法都应该正确地关闭存储对象,完成后(通常或有例外)。在“一段时间后自动停止”之后,您重新启动了多少次脚本?
  • @MaxU 谢谢。当他们无例外地停止时,我的脚本无法完成。当我尝试再次运行它时(它会从停止的地方开始),错误 [Errno 24] 出现并且脚本立即停止。所以如果我想运行脚本,我必须关闭 iPython 控制台并重新启动它才能运行
  • 你能显示一个你正在调用.to_hdf()pd.HDFStore()的循环吗?

标签: python pandas hdf5 hdfstore


【解决方案1】:

您可以使用psutil模块检查/列出Windows中属于Python进程的所有打开文件。

演示:

In [52]: [proc.open_files() for proc in psutil.process_iter() if proc.pid == os.getpid()]
Out[52]:
[[popenfile(path='C:\\Windows\\System32\\en-US\\KernelBase.dll.mui', fd=-1),
  popenfile(path='C:\\Users\\Max\\.ipython\\profile_default\\history.sqlite-journal', fd=-1),
  popenfile(path='C:\\Users\\Max\\.ipython\\profile_default\\history.sqlite', fd=-1)]]

我们完成以下块后,文件处理程序将立即关闭:

In [53]: with pd.HDFStore('d:/temp/1.h5', 'a') as hf:
   ....:     hf['df2'] = df
   ....:

证明:

In [54]: [proc.open_files() for proc in psutil.process_iter() if proc.pid == os.getpid()]
Out[54]:
[[popenfile(path='C:\\Windows\\System32\\en-US\\KernelBase.dll.mui', fd=-1),
  popenfile(path='C:\\Users\\Max\\.ipython\\profile_default\\history.sqlite', fd=-1)]]

检查psutil是否正常工作(注意D:\\temp\\aaa):

In [55]: fd = open('d:/temp/aaa', 'w')

In [56]: [proc.open_files() for proc in psutil.process_iter() if proc.pid == os.getpid()]
Out[56]:
[[popenfile(path='C:\\Windows\\System32\\en-US\\KernelBase.dll.mui', fd=-1),
  popenfile(path='D:\\temp\\aaa', fd=-1),
  popenfile(path='C:\\Users\\Max\\.ipython\\profile_default\\history.sqlite', fd=-1)]]

In [57]: fd.close()

In [58]: [proc.open_files() for proc in psutil.process_iter() if proc.pid == os.getpid()]
Out[58]:
[[popenfile(path='C:\\Windows\\System32\\en-US\\KernelBase.dll.mui', fd=-1),
  popenfile(path='C:\\Users\\Max\\.ipython\\profile_default\\history.sqlite', fd=-1)]]

因此,使用这种技术,您可以调试代码并找到在您的情况下打开文件的数量变得疯狂的地方

【讨论】:

  • 谢谢!我通过 Ctrl+C 停止了脚本并使用 psutil 检查,没有打开文件!事实上,我添加了逻辑来检查在此过程中是否打开了任何文件 - 关闭后没有打开任何文件!但是脚本异常停止后(无异常),有几件事被破坏:无法使用psutil(AttributeError:'module'对象没有属性'process_iter'),无法打开Excel文件(IOError:[Errno 24]打开太多文件:...),自动重新加载已损坏。同时,可以读取HDF文件,可以读取pickle文件。现在甚至不知道在哪里寻找问题......
  • 我认为您应该尝试找出the script was stopped abnormally (without exception) 时发生的情况... stopped abnormally 是什么意思?你怎么知道它停止了而不是挂/写/读/等待一些资源?
  • 脚本停止并返回 iPython 控制台。完全没有错误信息。我可以继续玩 comsole
  • @StanFish,我认为我无法帮助您看不到读取 Excel 文件并将结果写入 HDF5 文件的循环...
  • 异常停止意味着它不应该在循环完成之前停止。如果我打开另一个控制台并运行脚本,它会从它停止的地方继续
猜你喜欢
  • 2022-07-06
  • 2011-12-02
  • 2012-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多