python中出现意外的空格生成了字符串

时间:2012-04-21 08:06:25

标签: python formatting

我使用Python生成由很长行组成的ASCII文件。这是一个示例行(假设文件中的第100行,'[...]'由我添加以缩短行):

{6 1,14 1,[...],264 1,270 2,274 2,[...],478 1,479 8,485 1,[...]}

如果我打开使用ipython生成的ASCII文件:

f = open('myfile','r')
print repr(f.readlines()[99])

我确实获得了正确打印的预期行('[...]'由我添加以缩短行):

'{6 1,14 1,[...],264 1,270 2,274 2,[...],478 1,479 8,485 1,[...]}\n'

相反,如果我用想要读取它的程序打开这个文件,它会产生一个异常,在478 1之后抱怨意外的一对。 所以我尝试用 vim 打开文件。仍然 vim 显示没有问题,但如果我复制 vim 打印的行并将其粘贴到另一个文本编辑器中(在我的情况下 TextMate ) ,这是我获得的那条线('[...]'是我添加的,以缩短线条):

{6 1,14 1,[...],264 1,270      2,274 2,[...],478 1,4     79 8,485 1,[...]}

该线478 1后确实存在问题。 我尝试以不同的方式生成我的行(连接,使用cStringIO,...),但我总是得到这个结果。例如,当使用cStringIO时,生成的行如下所示(即使我试图改变它,也没有运气):

def _construct_arff(self,attributes,header,data_rows):
  """Create the string representation of a Weka ARFF file.
     *attributes* is a dictionary with attribute_name:attribute_type
       (e.g., 'num_of_days':'NUMERIC')
     *header* is a list of the attributes sorted
       (e.g., ['age','name','num_of_days'])
     *data_rows* is a list of lists with the values, sorted as in the header
       (e.g., [ [88,'John',465],[77,'Bob',223]]"""

  arff_str = cStringIO.StringIO()
  arff_str.write('@relation %s\n' % self.relation_name)

  for idx,att_name in enumerate(header):
    try:
      name = att_name.replace("\\","\\\\").replace("'","\\'")
      arff_str.write("@attribute '%s' %s\n" % (name,attributes[att_name]))
    except UnicodeEncodeError:
      arff_str.write('@attribute unicode_err_%s %s\n' 
                     % (idx,attributes[att_name]))

  arff_str.write('@data\n')
  for data_row in data_rows:
    row = []
    for att_idx,att_name in enumerate(header):
      att_type = attributes[att_name]
      value = data_row[att_idx]
      # numeric attributes can be sparse: None and zeros are not written
      if ((not att_type == constants.ARRF_NUMERIC)
          or not ((value == None) or value == 0)):
        row.append('%s %s' % (att_idx,value))
    arff_str.write('{' + (','.join(row)) + '}\n')
  return arff_str.getvalue()

UPDATE :从上面的代码中可以看出,该函数将给定的数据集转换为特殊的arff文件格式。我注意到我创建的其中一个属性包含数字作为字符串(例如,'1',而不是1)。通过强制这些数字为整数:

features[name] = int(value)

我成功重新创建了arff文件。但是我不知道这是一个值,它是如何对* att_idx *的格式产生影响的,它总是一个整数,同样由@JohnMachin和@gnibbler指出(感谢您的答案,顺便说一句) 。所以,即使我的代码现在运行,我仍然不明白为什么会发生这种情况。如果未正确转换为 int ,该值如何影响其他内容的格式化?

This file包含格式错误的版本。

1 个答案:

答案 0 :(得分:11)

内置函数repr是你的朋友。它会毫不含糊地向您显示文件中的内容。

这样做:

f = open('myfile','r')
print repr(f.readlines()[99])

并编辑您的问题以显示结果。

更新:关于它是如何实现的,无法分辨,因为它不能由您展示的代码生成。值37应该是att_idx的值,它来自enumerate(),因此必须是int。您使用%s格式化此int ... 37不能成为3rubbish7。此外,它应该按0,1等等生成att_idx,但是你缺少很多值,你的循环中没有任何条件。

请向我们展示您实际运行的代码。

<强>更新

同样,此代码将无法运行:

for idx,att_name in enumerate(header):
    arff_str.write("@attribute '%s' %s\n" % (name,attributes[att_name]))

因为name未定义;你可能意味着att_name

也许我们可以将所有这些内容缩短:在网络上的某个地方发布你的输出文件的副本(如果它很大,则压缩),这样我们就可以看到可能会扰乱其消费者的内容。请编辑您的问题,说出哪些线路表明问题。

顺便说一句,你说有些数据是字符串而不是整数,如果你通过int将数据强制转移到features[name] = int(value),问题就会消失......什么是'功能' ??什么是'名字'??

这些字符串是unicode而不是str吗?

更新2(在网上发布错误文件后)

没有提供有关哪一行显示问题的信息。事实证明,没有任何行显示属性479所描述的问题。我写了这个检查脚本:

import re, sys
# sample data line:
# {40 1,101 3,319 2,375 2,525 2,530 bug}
# Looks like all data lines end in ",530 bug}" or ",530 other}"
pattern1 = r"\{(?:\d+ \d+,)*\d+ \w+\}$"
matcher1 = re.compile(pattern1).match
pattern2 = r"\{(?:\d+ \d+,)*"
matcher2 = re.compile(pattern2).match
bad_atts = re.compile(r"\D\d+\s+\W").findall
got_data = False
for lino, line in enumerate(open(sys.argv[1], "r"), 1):
    if not got_data:
        got_data = line.startswith('@data')
        continue
    if not matcher1(line):
        print
        print lino, repr(line)
        m = matcher2(line)
        if m:
            print "OK up to offset", m.end()
            print bad_atts(line)

示例输出(包含在第80列):

581 '{2 1,7 1,9 1,12 1,13 1,14 1,15 1,16 1,17 1,18 1,21 1,22 1,24 1,25 1,26 1,27
 1,29 1,32 1,33 1,36 1,39 1,40 1,44 1,48 1,49 1,50 1,54 1,57 1,58 1,60 1,67 1,68
 1,69 1,71 1,74 1,75 1,76 1,77 1,80 1,88 1,93 1,101 ,103 6,104 2,109 20,110 3,11
2 2,114 1,119 17,120 4,124 39,128 5,137 1,138 1,139 1,162 1,168 1,172 18,175 1,1
76 6,179 1,180 1,181 2,185 2,187 9,188 8,190 1,193 1,195 2,196 4,197 1,199 3,201
 3,202 4,203 5,206 1,207 2,208 1,210 2,211 1,212 5,213 1,215 2,216 3,218 2,220 2
,221 3,225 8,226 1,233 1,241 4,242 1,248 5,254 2,255 1,257 4,258 4,260 1,266 1,2
68 1,269 3,270 2,271 5,273 1,276 1,277 1,280 1,282 1,283 11,285 1,288 1,289 1,29
6 8,298 1,299 1,303 1,304 11,306 5,308 1,309 8,310 1,315 3,316 1,319 11,320 5,32
1 11,322 2,329 1,342 2,345 1,349 1,353 2,355 2,358 3,359 1,362 1,367 2,368 1,369
 1,373 2,375 9,377 1,381 4,382 1,383 3,387 1,388 5,395 2,397 2,400 1,401 7,407 2
,412 1,416 1,419 2,421 2,422 1,425 2,427 1,431 1,433 7,434 1,435 1,436 2,440 1,4
49 1,454 2,455 1,460 3,461 1,463 1,467 1,470 1,471 2,472 7,477 2,478 11,479 31,4
82 6,485 7,487 1,490 2,492 16,494 2,495 1,497 1,499 1,501 1,502 1,503 1,504 11,5
06 3,510 2,515 1,516 2,517 3,518 1,522 4,523 2,524 1,525 4,527 2,528 7,529 3,530
 bug}\n'
OK up to offset 203
[',101 ,']

709 '{101 ,124 2,184 1,188 1,333 1,492 3,500 4,530 bug}\n'
OK up to offset 1
['{101 ,']

因此看起来att_idx == 101的属性有时可以包含空字符串''。您需要弄清楚如何处理此属性。如果您解开拜占庭代码,这将有助于您的思考:

  if ((not att_type == constants.ARRF_NUMERIC)
      or not ((value == None) or value == 0)):

除此之外:“expletive deleted”代码不会运行;它应该是ARFF,而不是ARRF

成:

if value or att_type != constants.ARFF_NUMERIC:

或者只是if value:,它会过滤掉所有None0""。请注意att_idx == 101对应于ARFF文件头中给定STRING类型的属性“priority”:

[line 103] @attribute 'priority' STRING

顺便说一下,关于features[name] = int(value)“修复”问题的陈述是非常可疑的; int("")引发了异常。

可以帮助您阅读此wiki section about sparse ARFF files末尾的警告。