python - 使用 Astropy 打开 FITS 时出现 OSError 24
问题描述
首先,我已经阅读了以下内容:
- 使用 astropy.io 读取 FITS 时出现 OSError 24(打开的文件过多)
- https://astropy.readthedocs.io/en/latest/io/fits/appendix/faq.html#im-opening-many-fits-files-in-a-loop-and-getting-oserror-too-many-打开文件
还有一些来自第一个的链接,但没有一个有效......
我的问题是在 Jupyter Notebook 中打开巨大的 (>80 Mb/pc.) 和大量 (~3000) FITS 文件。相关代码片段如下:
# Dictionary to store NxN data matrices of cropped image tiles
CroppedObjects = {}
# Defining some other, here used variable....
# ...
# Interate over all images ('j'), which contain the current object, indexed by 'i'
for i in range(0, len(finalObjects)):
for j in range(0, len(containingImages[containedObj[i]])):
countImages += 1
# Path to the current image: 'mnt/...'
current_image_path = ImagePaths[int(containingImages[containedObj[i]][j])]
# Open .fits images
with fits.open(current_image_path, memmap=False) as hdul:
# Collect image data
image_data = fits.getdata(current_image_path)
# Collect WCS data from the current .fits's header
ImageWCS = wcs.WCS(hdul[1].header)
# Cropping parameters:
# 1. Sky-coordinates of the croppable object
# 2. Size of the crop, already defined above
Coordinates = coordinates.SkyCoord(finalObjects[i][1]*u.deg,finalObjects[i][2]*u.deg, frame='fk5')
size = (cropSize*u.pixel, cropSize*u.pixel)
try:
# Cut out the image tile
cutout = Cutout2D(image_data, position=Coordinates, size=size, wcs=ImageWCS, mode='strict')
# Write the cutout to a new FITS file
cutout_filename = "Cropped_Images_Sorted/Cropped_" + str(containedObj[i]) + current_image_path[-23:]
# Sava data to dictionary
CroppedObjects[cutout_filename] = cutout.data
foundImages += 1
except:
pass
else:
del image_data
continue
# Memory maintainance
gc.collect()
# Progress bar
sys.stdout.write("\rProgress: [{0}{1}] {2:.3f}%\tElapsed: {3}\tRemaining: {4} {5}".format(u'\u2588' * int(countImages/allCrops * progressbar_width),
u'\u2591' * (progressbar_width - int(countImages/allCrops * progressbar_width)),
countImages/allCrops * 100,
datetime.now()-starttime,
(datetime.now()-starttime)/countImages * (allCrops - countImages),
foundImages))
sys.stdout.flush()
好吧,它实际上做了三件事:
- 打开特定的 FITS 文件
- 从中切出一个正方形(但是
strict
,如果数组仅部分重叠,则try
语句跳转到循环中的下一步) - 更新进度条
然后转到下一个文件,做同样的事情并遍历我所有的 FITS 文件。
但是:如果我尝试运行此代码,在找到大约 1000 张图片后,它会停止并给出并OSError: [Errno 24] Too many open files
在线:
image_data = fits.getdata(current_image_path)
我尝试了所有应该解决问题的方法,但没有任何帮助...甚至没有将内存映射设置为false
或使用fits.getdata
and gc.collect()
...还尝试了许多小的更改,例如在没有try
语句的情况下运行,切掉所有图像图块,没有任何限制。del
else语句里面也是我的又一次惨痛尝试。我还能尝试什么来使它最终起作用?
另外,如果有不清楚的地方,请随时问我!我也会尽力帮助你理解问题!
解决方案
我过去也遇到过类似的问题(请参阅此处)。最后我让它大致像这样工作:
total = 0
for filename in filenames:
with fits.open(filename, memmap=False) as hdulist:
data = hdulist['spam'].data
total += data.sum()
一些注意事项:
- 用于
fits.open
打开文件,使用memmap=False
- 在 with 块中使用它,以使文件关闭可靠
- 保持 with 块简短,只需将您需要的数据加载到内存中,然后通过退出来关闭文件
- 关闭文件后对数据执行您需要执行的操作;这可能并不真正需要,但如果 Python 对文件中数据的引用是阻止它被关闭的问题,这可以简化情况。我不认为剪切代码是您示例中的问题,但它可能是 - 尝试取消注释它?
- 不要做额外的事情
fits.getdata
,我认为会再次打开文件 - 并且不应该是必需的
del
,gc.collect
如果代码按照这里建议的那样简单,就不会有循环引用,Python 将可靠地删除作用域末尾的对象
现在这可能无济于事,您仍然会遇到问题。在这种情况下,继续进行的方法是制作一个对 Astropy 开发人员可以运行的对您不起作用的最小可重复示例(就像我在这里所做的那样),然后向 Astropy 提出问题,提供您的 Python 版本,Astropy 版本和操作系统,或在此处发布。关键是:这很复杂,并且可能取决于运行时/版本,因此需要尝试确定任何人都可以运行的示例,但对您来说失败了。
推荐阅读
- c++ - 错误:'int' 和 ' 类型的无效操作数
' 到二进制 '运算符<=' - r - R逻辑运算符无法按顺序检测值
- azure-cosmosdb - 当 parquet 类型不正确时如何指定 CosmosDb Synapse Link 类型?
- deep-learning - 为什么要将马尔可夫属性引入强化学习?
- java - Java Spark:如何从整个数据集的 JSON 格式字符串的列中获取值?
- java - 如何解码base64
- typescript - TypeScript:如何接受交互的泛型类型?
- c# - AWS EC2 Dotnet netcoreapp3.1 在我的手机上工作但在我的电脑上不工作
- c# - 如何使用公钥加密字符串并使用 MimeKit 使用私钥解密?
- flutter - 有没有办法在手机锁定时保持计时器运行?