Skip to main content
 首页 » 编程设计

python之python 生成的字符串中的意外空格

2025年05月04日11davidwang456

我正在使用 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包含格式错误的版本。

请您参考如下方法:

内置函数repr是你的 friend 。它会明确地向您显示文件中的内容。

这样做:

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

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

更新:至于它是如何到达那里的,这是不可能的,因为它不可能是由您显示的代码生成的。值 37 应该是来自 enumerate() 的 att_idx 值,因此必须是一个 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。

也许我们可以绕过所有这些东西:将输出文件的副本(如果它很大则压缩)发布到网络上的某个地方,这样我们就可以亲眼看到什么可能会打扰它的消费者。请编辑您的问题,说明哪一行显示了问题。

顺便说一句,你说一些数据是字符串而不是整数,如果你通过执行 features[name] = int(值) ...什么是“功能”?什么是“名字”??

这些字符串中的任何一个都是 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)): 

除此之外:“脏话已删除”的代码不会运行;应该是ARFF,不是ARRF

进入:

if value or att_type != constants.ARFF_NUMERIC: 

或者可能只是 if value: 这将过滤掉所有 None、0 和 "" .请注意,att_idx == 101 对应于属性“priority”,它在 ARFF 文件头中被赋予 STRING 类型:

[line 103] @attribute 'priority' STRING 

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

它可能会帮助您阅读此 wiki section about sparse ARFF files 末尾的警告.