.write()之后,我的文件不断关闭

时间:2018-08-27 09:22:25

标签: python

这是我要完成的这段代码:

from symfit import Derivative

dy1dt = Derivative(y1, t)
dy2dt = Derivative(y2, t)
constraints = [
    Eq(y1.subs({t: t0}), y2.subs({t: t0})),
    Eq(dy1dt.subs({t: t0}), dy2dt.subs({t: t0}))
]

所以从本质上讲,我试图将文件的统计信息写入正在复制的新文件中。统计信息可以正常工作,就像打开文件时一样,统计信息都已写入。但是,由于有两个outfile.write,我注意到它似乎在第一个文件之后关闭,因此只有统计信息进入了,其余的都没有。原始文件中的内容。

我得到的错误是:

elif parameter == 'statistics':
    outfile.write(stats(infile))
    for line in infile:
        outfile.write(line)

我不确定为什么要关闭文件。

编辑:这是根据要求的完整代码

ValueError: I/O operation on closed file.

EDIT2:非常抱歉不包含它。这是统计信息功能:

def copy_file():
    infile_name = input("Please enter the name of the file to copy: ")
    infile = open(infile_name, 'r', encoding='utf8')
    parameter = input("Please enter a parameter(line numbers, Gutenberg trim, statistics, none): ")
    outfile_name = input("Please enter the name of the new copy:  ")
    outfile = open(outfile_name, 'w', encoding='utf8')
    counter = 1
    if parameter == 'line numbers':
        for line in infile:
            outfile.write(f' {counter:6}: {line}')
            counter += 1
    elif parameter == 'Gutenberg trim':
        copyStart = False
        for line in infile:
            #print(line.strip())
            if '*** START' in line.strip():
                copyStart = True
                continue
            elif '*** END' in line.strip():
                copyStart = False
                break
            if copyStart == True:
                outfile.write(line)
    elif parameter == 'statistics':
        outfile.write(stats(infile))
        for line in infile:
            outfile.write(line)
    else:
        for line in infile:
            outfile.write(line)
    infile.close()
    outfile.close()
copy_file()

以下是统计信息的结果:

def stats(text) -> str:
    with text as infile:
        totallines = 0
        emplines = 0
        characters = 0
        for line in infile:
            totallines += 1
            characters += len(line)
            if len(line.strip()) == 0:
                emplines += 1
        lines = totallines - emplines
        totalaveChars = characters/totallines
        nonempaveChars = characters/lines
        result = (f'{totallines:5} lines in list \n'
                  f'{emplines:5} empty lines in list \n'
                  f'{totalaveChars:5.1f} average characters per line \n'
                  f'{nonempaveChars:5.1f} average chars per non-empty line')
        return result
print(stats(open('ASH.txt', 'r', encoding='utf8')))

3 个答案:

答案 0 :(得分:4)

问题出在stats函数中。 with语句将关闭带有本地名称文本的文件,在您的情况下为infile!

def stats(text) -> str:
    totallines = 0
    emplines = 0
    characters = 0
    for line in text:
        totallines += 1
        characters += len(line)
        if len(line.strip()) == 0:
            emplines += 1
    lines = totallines - emplines
    totalaveChars = characters/totallines
    nonempaveChars = characters/lines
    result = (f'{totallines:5} lines in list \n'
              f'{emplines:5} empty lines in list \n'
              f'{totalaveChars:5.1f} average characters per line \n'
              f'{nonempaveChars:5.1f} average chars per non-empty line')
    return result

在主程序中,您将变量stats传递给了函数infile,该变量是一个文件。您无需在stats函数内使用with重新打开它。此外,with将确保结束。因此,在您的主循环中,infile在调用stats之后关闭。

答案 1 :(得分:0)

尝试以下操作;

def copy_file():
    infile_name = input("Please enter the name of the file to copy: ")
    parameter = input("Please enter a parameter(line numbers, Gutenberg trim, statistics, none): ")
    outfile_name = input("Please enter the name of the new copy:  ")
    counter = 1
    with open(infile_name, 'r', encoding='utf8') as infile:
      with open(outfile_name, 'w', encoding='utf8') as outfile:
          if parameter == 'line numbers':
              for line in infile:
                  outfile.write(f' {counter:6}: {line}')
                  counter += 1
          elif parameter == 'Gutenberg trim':
              copyStart = False
              for line in infile:
                  #print(line.strip())
                  if '*** START' in line.strip():
                      copyStart = True
                      continue
                  elif '*** END' in line.strip():
                      copyStart = False
                      break
                  if copyStart == True:
                      outfile.write(line)
          elif parameter == 'statistics':
              outfile.write(stats(infile))
              for line in infile:
                  outfile.write(line)
          else:
              for line in infile:
                  outfile.write(line)
    copy_file()

使用with open(filename, 'r') as file:,它将在操作完成后而不是之后自动关闭文件。

答案 2 :(得分:0)

     elif parameter == 'statistics':
         outfile.write(stats(infile))
         for line in infile:
             outfile.write(line)
     

...仅显示统计信息,不显示统计信息中的其余内容   原始文件...

我的有根据的猜测是stats函数会消耗,并且可能 关闭输入流(IS)。

如果stats表现良好,并且仅限于使用 IS,可以快退

           ...
           infile.seek(0) # rewind the input stream
           for line in infile:
               outfile.write(line)

另一方面,如果stats有点破坏性并且关闭了 IS可以一起使用文件对象的.name属性 重新打开它,像这样

           ...
           for line in open(infile.name):
               outfile.write(line)

即使在第一个较温和的假设和 即使代码是通过infile文件对象传递的 外部呼叫。

另一种可能,如果您可以访问和修改stats源 代码,以撤消该功能执行的读取操作,以记忆 任何read操作之前输入流中的当前位置 然后将IS倒带到该位置

def stats(infile):
    ...
    current_pos = infile.tell()
    # do your stuff
    ...
    infile.seek(current_pos)
    return workload

为此,当然,不必关闭文件对象 在.seek()之前,显式地(通过.close())或 隐式地(通过超出with块的范围)。
如果您是这种情况(已关闭文件),请删除 明确的infile.close()或(不必要的)with语句,以及 倒带将是正确的。