如何在python中的csv.reader中使用pkgutils.get_data?

Kar*_*l P 2 python

我有一个python模块,其中包含各种数据文件(代表曲线的一组csv文件),需要在运行时加载。csv模块效果很好

  # curvefile = "ntc.10k.csv"
  raw = csv.reader(open(curvefile, 'rb'), delimiter=',')
Run Code Online (Sandbox Code Playgroud)

但是,如果我将此模块导入另一个脚本,则需要找到数据文件的完整路径。

/project
   /shared
       curve.py
       ntc.10k.csv
       ntc.2k5.csv
   /apps
       script.py
Run Code Online (Sandbox Code Playgroud)

我希望script.py仅按基本文件名而不是完整路径来引用曲线。在模块代码中,我可以使用:

pkgutil.get_data("curve", "ntc.10k.csv") 
Run Code Online (Sandbox Code Playgroud)

可以很好地找到文件,但是它返回已读入的csv文件,而csv.reader需要文件句柄本身。有什么方法可以使这两个模块一起正常工作?它们都是标准的库模块,因此我并不是真的期望出现问题。我知道我可以开始拆分pkgutil二进制文件数据,但是那样的话我也可能不使用csv库。

我知道我可以只在模块代码中使用它,而不必理会pkgutils,但看起来pkgutils确实正是此目的。

this_dir, this_filename = os.path.split(__file__)
DATA_PATH = os.path.join(this_dir, curvefile)
raw = csv.reader(open(DATA_PATH, "rb"))
Run Code Online (Sandbox Code Playgroud)

小智 6

我打开了的源代码get_data,让它返回文件而不是已加载文件的路径很简单。这个模块应该可以解决问题。使用关键字as_string=True返回读入内存的文件,或者使用as_string=False,返回路径。

import os, sys

from pkgutil import get_loader

def get_data_smart(package, resource, as_string=True):
"""Rewrite of pkgutil.get_data() that actually lets the user determine if data should
be returned read into memory (aka as_string=True) or just return the file path.
"""

loader = get_loader(package)
if loader is None or not hasattr(loader, 'get_data'):
    return None
mod = sys.modules.get(package) or loader.load_module(package)
if mod is None or not hasattr(mod, '__file__'):
    return None

# Modify the resource name to be compatible with the loader.get_data
# signature - an os.path format "filename" starting with the dirname of
# the package's __file__
parts = resource.split('/')
parts.insert(0, os.path.dirname(mod.__file__))
resource_name = os.path.join(*parts)
if as_string:
    return loader.get_data(resource_name)
else:
    return resource_name
Run Code Online (Sandbox Code Playgroud)


Tho*_*s K 2

这并不理想,特别是对于非常大的文件,但您可以使用StringIO将字符串转换为带有 read() 方法的内容,csv.reader 应该能够处理。

csvdata = pkgutil.get_data("curve", "ntc.10k.csv") 
csvio = StringIO(csvdata)
raw = csv.reader(csvio)
Run Code Online (Sandbox Code Playgroud)