【问题标题】:Difficulty utilizing Python struct.Struct.unpack_from with different format strings难以使用具有不同格式字符串的 Python struct.Struct.unpack_from
【发布时间】:2014-03-21 15:52:34
【问题描述】:

第一次发帖,长期潜伏。已经到处搜索了这个问题的答案,但它已经到了那个阶段......!

我在执行 John Machin 对上一个问题给出的答案时遇到了一些麻烦:

How to efficiently parse fixed width files?

在非常高的层次上,我正在使用此代码拆分固定格式的文本文件并将它们导入 PostgreSQL 数据库。我已经成功地使用此代码实现了一个文本文件的解决方案,但是我现在正在尝试扩展我的程序以处理具有不同固定格式的不同文本文件,并且不断遇到相同的错误:

struct.error: unpack_from requires a buffer of at least [x] bytes

当然,根据我提供给函数的格式字符串,我得到不同的 x 值 - 我的问题是它继续适用于一种且仅适用于一种格式,而不适用于任何其他格式。我唯一要更改的是用于计算格式字符串的变量,以及脚本中与格式相关的变量名称。

例如,这可以正常工作:

cnv_text = lambda s: str(s.strip())
cnv_int = lambda s: int(s) if s.isspace() is False else s.strip()
cnv_date_ymd = lambda s: datetime.datetime.strptime(s, '%Y%m%d') if s.isspace() is False else s.strip() # YYYY-MM-DD

unpack_len = 0
unpack_fmt = ""
splitData = []

conn = psycopg2.connect("[connection info]")
cur = conn.cursor()

Table1specs = [
    ('A', 6, 14, cnv_text),
    ('B', 20, 255, cnv_text),
    ('C', 275, 1, cnv_text),
    ('D', 276, 1, cnv_text),
    ('E', 277, 1, cnv_text),
    ('F', 278, 1, cnv_text),
    ('G', 279, 1, cnv_text),
    ('H', 280, 1, cnv_text),
    ('I', 281, 8, cnv_date_ymd),
    ('J', 289, 8, cnv_date_ymd),
    ('K', 297, 8, cnv_date_ymd),
    ('L', 305, 8, cnv_date_ymd),
    ('M', 313, 8, cnv_date_ymd),
    ('N', 321, 1, cnv_text),
    ('O', 335, 2, cnv_text),
    ('P', 337, 2, cnv_int),
    ('Q', 339, 5, cnv_int),
    ('R', 344, 255, cnv_text),
    ('S', 599, 1, cnv_int),
    ('T', 600, 1, cnv_int),
    ('U', 601, 5, cnv_int),
    ('V', 606, 10, cnv_text)
    ]

#for each column in the spec variable...
for column in Table1specs:
    start = column[1] - 1
    end = start + column[2]
    if start > unpack_len:
    unpack_fmt += str(start - unpack_len) + "x"
    unpack_fmt += str(end - start) + "s"
unpack_len = end
field_indices = range(len(Table1specs))
print unpack_len, unpack_fmt
#set unpacker
unpacker = struct.Struct(unpack_fmt).unpack_from

class Record(object):
    pass

filename = "Table1Data.txt"

f = open(filename, 'r')
for line in f:
    raw_fields = unpacker(line)
    r = Record()
    for x in field_indices:
        setattr(r, Table1specs[x][0], Table1specs[x][3](raw_fields[x]))
    splitData.append(r.__dict__)

所有数据都附加到 splitData 中,然后我在一个循环中循环并工作到 SQL 语句中,以便通过 psycopg2 输入到数据库中。当我将规格更改为其他内容(以及其他变量也反映这一点)时,我会收到错误消息。它是从 'raw_fields = unpacker(line)' 行抛出的。

我已经用尽了所有资源并且处于无所适从的状态...欢迎任何想法或想法。

(可能与我从中导入的文本文件有关吗?)

最好的问候。

【问题讨论】:

  • 你能给我们一些最小的工作示例代码来重现这个错误吗?
  • @alKid 在代码示例中添加 - 类似于来自链接问题的答案中的代码,这就是我最初不包括在内的原因:)。
  • @user3446927 - 您的示例被标记为“这很好用”。请提供一个失败的代码示例。
  • @Rob,现在已经解决了这个问题。问题在于我正在解析的文本文件 - 行不够长,所以我编写了一个函数,将空格写入每行的末尾以使它们成为正确的长度......到目前为止似乎工作正常。跨度>
  • 优秀。请删除此问题,以免其他人不必要地花费时间。

标签: python c parsing struct buffer


【解决方案1】:

已经解决了这个问题:问题是由我正在解析的文本文件引起的。这些行不够长,所以我编写了一个函数,将空格写入每行的末尾以使它们成为正确的长度:

def checkLineLength(checkFile, minLength):
    print ('Checking length of lines in file '+ checkFile+', where minimum line length is '+str(minLength))
    counter = 0
    fixedFile = 'fixed'+checkFile
    src = open(checkFile, 'r')
    dest = open(fixedFile, 'w')
    lines = src.readlines()
    for line in lines:
        if len(line) < minLength:
            x = (line.rstrip('\r\n') + (" "*(minLength-(len(line)-1))+'\r\n'))
            dest.write(x)
            counter += 1
        else:
            dest.write(line)
    if counter > 0:
        os.remove(checkFile)
        os.rename(fixedFile, checkFile)
        print (str(counter) + " lines fixed in "+ checkFile)

else:
    print('Line length in '+checkFile+' is fine.' )
    os.remove(fixedFile)

【讨论】:

    猜你喜欢
    • 2015-07-23
    • 2012-09-01
    • 2020-02-01
    • 2021-11-26
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    • 2020-07-27
    • 1970-01-01
    相关资源
    最近更新 更多