【问题标题】:Type Error when running a large function in Python在 Python 中运行大型函数时输入错误
【发布时间】:2013-12-04 20:29:02
【问题描述】:

我正在尝试运行一个大型函数,该函数将通过将大型文本文件拆分为扬声器及其语音,然后将语音进一步处理为组件段落来处理大型文本文件。这是代码:

import os
import re
import csv
from bs4 import BeautifulSoup

def driver(folder, input_filename, output_filename1, output_filename2):
    os.chdir(folder)
    with open(input_filename, 'r') as f:
        Hearing = f.read()
    hearing = BeautifulSoup(Hearing)
    hearing = hearing.get_text()
    hearing = hearing.split("RESPONSE TO WRITTEN")
    str (hearing)
    speakers = re.findall("\\n    Mr. [A-Z][a-z]+\.|\\n    Ms. [A-Z][a-z]+\.|\\n    Congressman [A-Z][a-z]+\.|\\n   Congresswoman [A-Z][a-z]+\.|\\n   Chairwoman [A-Z][a-z]+\.|\\n   Chairman [A-Z][a-z]+\.", hearing)
    speakers = list(set(speakers))
    #print speakers
    position = []
    for speaker in speakers:
        x = hearing.find(speakers)
        position.append(x)
        def find_speaker(hearing, speakers):
            position = []
            for speaker in speakers:
                x = hearing.find(speaker)
                if x==-1:
                    x += 1000000
                position.append(x)
                first = min(position)
                name = speakers[position.index(min(position))]
            name_length = len(name)
            chunk = [name, hearing[0:first], hearing[first+name_length:]]
            #return chunk
            chunks = []
            #print hearing
            names = []
            while len(hearing)>10:
                chunk_try = find_speaker(hearing, speakers)
                hearing = chunk_try[2]
                chunks.append(chunk_try[1])
                names.append(chunk_try[0].strip())
                print len(hearing)#0
                chunks.append(hearing)
                chunks = chunks[1:]
                print len(names) 
                print len(chunks)
                data = zip(names, chunks)
                with open(output_filename1,'wb') as f:
                    w=csv.writer(f)
                    w.writerow(['Speaker','Speech'])
                    for row in data:
                        w.writerow(row)
                        paragraphs = str(chunks)
                        print (paragraphs)
                        Paragraphs = paragraphs.split("\\n")
                        data1 = zip(Paragraphs)
                        with open(output_filename2,'wb') as f:
                            w=csv.writer(f)
                            w.writerow(['Paragraphs'])
                            for row in data1:
                                w.writerow(row)
                                return True 
driver("C:/Users/Documents/Congressional Hearings/NHTF Project/Test Set", 'CHRG-107hhrg70750.htm', 'CHRG-107hhrg70750.csv', 'Paragraphs.csv')

但是,当我运行驱动程序功能时,我收到以下错误:

Traceback (most recent call last):
  File "<pyshell#159>", line 1, in <module>
    driver("C:/Users/mboogie/Documents/Congressional Hearings/NHTF Project/Test Set", 'CHRG-107hhrg70750.htm', 'CHRG-107hhrg70750.csv', 'Paragraphs.csv')
  File "<pyshell#158>", line 9, in driver
    speakers = re.findall("\\n    Mr. [A-Z][a-z]+\.|\\n    Ms. [A-Z][a-z]+\.|\\n    Congressman [A-Z][a-z]+\.|\\n   Congresswoman [A-Z][a-z]+\.|\\n   Chairwoman [A-Z][a-z]+\.|\\n   Chairman [A-Z][a-z]+\.", hearing)
  File "C:\Python27\lib\re.py", line 177, in findall
    return _compile(pattern, flags).findall(string)
TypeError: expected string or buffer

我以为这是指文件 'hearing' 没有带字符串,但是当我尝试 str(hearing) 时,它并没有解决错误。我也很困惑为什么它指的是三行单独的代码。任何建议都将不胜感激 - 我已经坚持了很长一段时间!

【问题讨论】:

  • 你认为“str(hearing)”会做什么?
  • 它指的是三行代码,因为这就是所谓的; &lt;module&gt; 在第 1 行调用 driverdriver 在第 9 行调用 re.findall(),然后 re.findall 尝试调用 return _compile(...).findall(...),其中引发了 TypeError。这称为“回溯”。
  • 听证会是一个列表,从拆分,有时只需简单地添加一个打印听证会,就会告诉你问题出在哪里。而 str(hearing) 没有任何帮助,因为它的结果被分配给了任何人。
  • 这段代码很难理解,但我不认为嵌套两个with opens,两者都改变​​wf,会做你想做的事。

标签: python csv split


【解决方案1】:

您的代码结构有点混乱,但我会尝试解释发生了什么。

当你到达这条线时:

speakers = re.findall("\\n    Mr. [A-Z][a-z]+\.|\\n    Ms. [A-Z][a-z]+\.|\\n    Congressman [A-Z][a-z]+\.|\\n   Congresswoman [A-Z][a-z]+\.|\\n   Chairwoman [A-Z][a-z]+\.|\\n   Chairman [A-Z][a-z]+\.", hearing)

hearing 是一个列表,因为你用str.split 把它变成了上面的两行

hearing = hearing.split("RESPONSE TO WRITTEN")

因此,您会收到一个错误,因为re.findall 不支持将列表作为其第二个参数。相反,它需要一个字符串或缓冲区。


现在,这就是问题所在。解决方案是将re.findall 的第二个参数设为字符串。该字符串的来源取决于您想要做什么。

从这一行来看:

str (hearing)

认为您想将列表hearing 变成其自身的字符串表示形式。如果是这样,那么您需要像这样重新分配hearing

hearing = str(hearing)

【讨论】:

  • 谢谢!这消除了错误,但调用该函数不会产生所需的 3 个 .csv 文件。任何调试的想法?我曾考虑将其分解为三个较小的函数——这可能会使它更易于管理,但随后我必须手动运行我的 578 个文本文件。我正在尝试使用该功能自动化该过程。
  • @MYR - 不,不要拆散它。相反,您应该使用称为“逐步执行代码”的编码帮助。基本上,一次构建所有东西,并且只有在该部分完美运行时才能继续。虽然这需要更长的时间,但这样做可以更好地防止错误和逻辑缺陷。例如,你会注意到你的最后一个 for 循环只会运行一次,因为它有一个 return 语句。
【解决方案2】:

您将所有内容都放在一个单一的代码块中,这使得测试或修改变得更加困难。我改写如下:

from bs4 import BeautifulSoup
from collections import namedtuple
import csv
from itertools import tee, izip
import os, os.path
import re

DIR       = r'C:\Users\Documents\Congressional Hearings\NHTF Project\Test Set'
HARD_WRAP = re.compile(r'\n(?!    )')
SPEAKERS  = re.compile(r'^    (Mr.|Mrs.|Congressman|Congresswoman|Chairman|Chairwoman) ([a-zA-Z \-]{2,40})\.', re.MULTILINE)
NAME      = lambda m: '{0} {1}'.format(*m.groups())
Speaker   = namedtuple('Speaker', ['name', 'name_start', 'name_end'])

def load_hearing_response(fname, split_on='    Present:'):
    with open(fname, 'rU') as inf:
        html = inf.read()
    txt  = BeautifulSoup(html).get_text()
    return txt.rsplit(split_on, 1)[-1]     # return everything after last occurrence of split_on

def un_hard_wrap(txt, reg=HARD_WRAP):
    return reg.sub('', txt)

def pairwise(iterable):
    a,b = tee(iterable)
    next(b, None)
    return izip(a, b)

def get_speeches(txt):
    speakers = [Speaker(NAME(sp), sp.start(), sp.end()) for sp in SPEAKERS.finditer(txt)]
    speakers.append(Speaker('', len(txt), None))    # tail sentinel for pairwise processing
    return [(this.name, txt[this.name_end:nxt.name_start]) for this,nxt in pairwise(speakers)]

def write_csv(fname, data, header=None):
    with open(fname, 'wb') as outf:
        out_csv = csv.writer(outf)
        if header is not None:
            out_csv.writerow(header)
        out_csv.writerows(data)

def main():
    # get text of Congressional hearing responses
    txt = load_hearing_response(os.path.join(DIR, 'CHRG-107hhrg70750.htm'))
    txt = un_hard_wrap(txt)
    # break into speeches
    speeches = get_speeches(txt)
    # write (speaker, speech) pairs to a .csv file
    write_csv(os.path.join(DIR, 'CHRG-107hhrg70750.csv'), speeches, ['Speaker', 'Speech'])
    # write paragraphs of speeches to a .csv file
    paragraphs = ([para.strip()] for speaker,speech in speeches for para in speech.split('\n') if para.strip())
    write_csv(os.path.join(DIR, 'Paragraphs.csv'), paragraphs, ['Paragraphs'])

if __name__=="__main__":
    main()

请注意,这是未经测试的,因为我没有原始数据文件。

编辑:在被指向a sample data file后,我做了以下更改:

  1. 文本被硬包装;我添加了一个un_hard_wrap() 函数来转换回未包装的文本(每个段落后跟'\n')。

  2. 我在get_speeches() 中出错,使用sp.pos 代替sp.start()sp.end_pos 代替sp.end()。现在已修复此问题。

  3. 我调整了 SPEAKERS 正则表达式以消除一些误报(即演讲者说“演讲者先生,我冒犯了...”,并且被“演讲者先生”检测为演讲'.) 现在应该解决这个问题 - 除非它们以 40 个字符以下的句子开头。如果您知道可能的最长扬声器姓氏,您可以适当地调整 SPEAKERS 正则表达式,即 {2,40} 可以变为 {2,26} 或任何适当的最大长度。

  4. 我将... if para.strip() 添加到paragraphs 理解中以去除空段落。

【讨论】:

  • 这比我原来的优雅多了。我想出了这个错误 - Traceback (most recent call last): File "&lt;pyshell#145&gt;", line 2, in &lt;module&gt; main() File "&lt;pyshell#142&gt;", line 5, in main speeches = get_speeches(txt) File "&lt;pyshell#124&gt;", line 4, in get_speeches return [(this.name, txt[this.name_end:nxt.name_start]) for this,nxt in pairwise(speeches)] NameError: global name 'speeches' is not defined
  • 如此接近!这可行,但创建的 .csv 文件没有段落文本。我得到的只是第一个文件中的扬声器名称和第二个文件中的列标题paragraph。仍然很有帮助,因为这是该过程第一次真正实现完全自动化。
  • @MYR: 如果你把 .htm 文件发给我,我会做一些调试——hugh_bothwell (at) hotmail (dot) com
  • @MYR:如上所做的更改。希望有帮助!如果您有任何其他问题,请告诉我:-)
  • 绝对精彩!!!你不知道我已经为此工作了多长时间 - 惊人的答案!这非常有效!
【解决方案3】:
hearing = hearing.split("RESPONSE TO WRITTEN")
str (hearing)

str.split() 返回一个字符串列表。然后,当您调用 str() 将其转换回字符串时,您不会将返回值分配给任何名称。试试:

hearing = str(hearing)

或者,更好的是,找出您需要将字符串拆分为列表的哪个元素,并将其传递给re.findall

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-20
    • 1970-01-01
    • 2022-12-18
    • 2021-12-26
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    相关资源
    最近更新 更多