我正在尝试通过 .NET Framework DLL 打开一个大文件并访问 python 中的数据。
如果比我对这个工具有更多经验的人看到我正在尝试做的Python方面的任何问题,我会很乐意修复我的代码,否则如果你认为这可能是一个真正的问题,我会用我的更正来提出拉取请求这样每个人都可以从中受益。
更新添加的代码
import pythonnet
from pythonnet import load
load("netfx")
import clr
from time import time
try:
clr.AddReference('FileManager.Library')
import FileManager.Library
except System.IO.FileNotFoundException:
print("[File loader] DLL not found!")
class FileLoader:
def __init__(self, filePath):
self.dataLoader = FileManager.Library.FileReader(filePath)
self.isClosed = False
def load_data(self):
return self.dataLoader.GetDataPoints()
def close(self):
self.dataLoader.Close()
self.isClosed = True
def __del__(self):
print(f"[FileLoader - {time()}] Freeing memory!", flush=True)
if not self.isClosed:
self.close()
from FileManager.FileLoader import FileLoader
if __name__ == "__main__":
fl = FileLoader("data.csv")
data = fl.load_data()
print("Done!")
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace FileManager.Library
{
public class FileReader: IDisposable
{
private string filePath;
private int objectId;
private bool isDisposed = false;
private List<DataPoint> fileContent;
private DateTimeOffset dto = new DateTimeOffset(DateTime.UtcNow);
~FileReader() {
if(!isDisposed)
Dispose();
System.Console.WriteLine($"[C# - {dto.ToUnixTimeMilliseconds().ToString()} ] Deleting {objectId}");
}
public FileReader(string filePath)
{
this.filePath = filePath;
fileContent = new List<DataPoint>();
objectId = this.GetHashCode();
LoadFile();
}
private void LoadFile()
{
if (!File.Exists(filePath))
{
throw new FileNotFoundException($"Cannot open file{filePath}");
}
const Int32 BufferSize = 128;
using (var fileStream = File.OpenRead(filePath))
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8, true, BufferSize))
{
String line;
while ((line = streamReader.ReadLine()) != null)
{
var data = line.Split(',');
var dataPoint = new DataPoint((int)Convert.ToDouble(data[0]), Convert.ToDouble(data[1]));
fileContent.Add(dataPoint);
}
fileStream.Close();
}
return;
}
public DataPoint GetDataPoint(int i)
{
return fileContent[i];
}
public List<DataPoint> GetDataPoints()
{
return fileContent;
}
public void Dispose() {
if (isDisposed) return;
System.Console.WriteLine($"[C# - {dto.ToUnixTimeMilliseconds().ToString()}] Disoposing Obj {objectId}");
isDisposed = true;
}
public void Close() {
System.Console.WriteLine("Dummy things That I have to do before closing");
}
}
}
使用调试器运行上面的 python main 工作正常(时间戳也按正确的顺序),但如果没有调试器,我总是得到以下错误:
Dummy things That I have to do before closing
Done!
[C# - 1698683227427] Disoposing Obj 26765710
[C# - 1698683227427 ] Deleting 26765710
[FileLoader - 1698683227.5009353] Freeing memory!
Exception ignored in: <function FileLoader.__del__ at 0x00000158F00920D0>
Traceback (most recent call last):
File "FileLoader.py", line 30, in __del__
TypeError: 'MethodObject' object is not callable
我哪里错了?我该如何解决它?
注1:显然我不想尝试抓住它我希望它正常工作
注 2: C# 中的相同 main 完全没有错误
您似乎遇到了一个问题,即在 C# 析构函数之后调用 Python 垃圾收集器(
__del__
函数),导致错误,因为 C# 对象已被释放。发生这种情况是因为 Python 和 .NET 具有不同的内存管理模型。您可以在 Python 代码中显式调用 gc.collect()
,以确保在 C# 析构函数之前调用 Python 中的 __del__
方法。在Python中,可以使用gc.collect()
方法来手动激活垃圾收集。
import pythonnet
from pythonnet import load
import gc # Import the gc module
# ... Your other imports ...
class FileLoader:
def __init__(self, filePath):
self.dataLoader = FileManager.Library.FileReader(filePath)
self.isClosed = False
# ... Your other methods ...
def __del__(self):
print(f"[FileLoader - {time()}] Freeing memory!", flush=True)
if not self.isClosed:
self.close()
# Force a garbage collection here
gc.collect()