вставить строку в середине файла, заданного файлового объекта - PullRequest
0 голосов
/ 29 октября 2009

Я работаю над проблемой и застрял у стены

У меня есть (потенциально большой) набор текстовых файлов, и мне нужно применить к нему последовательность фильтров и преобразований и экспортировать его в некоторые другие места.

так что у меня примерно есть

def apply_filter_transformer(basepath = None, newpath = None, fts= None):
    #because all the raw studies in basepath should not be modified, so I first cp all to newpath
    for i in listdir(basepath):
        file(path.join(newpath, i), "wb").writelines(file(path.join(basepath, i)).readlines())
    for i in listdir(newpath):
        fileobj = open(path.join(newpath, i), "r+")
        for fcn in fts:
            fileobj = fcn(fileobj)
        if fileobj is not None:
            fileobj.writelines(fileobj.readlines())
        try:
            fileobj.close()
        except:
            print i, "at", fcn
            pass
def main():
    apply_filter_transformer(path.join(pardir, pardir, "studies"),
                         path.abspath(path.join(pardir, pardir, "filtered_studies")),
                         [
                        #transformer_addMemo,
                          filter_executable,
                          transformer_identity,
                          filter_identity,
                          ])

и fts в apply_filter_transformer - это список функций, который принимает объект файла Python и возвращает объект файла Python. Проблема, с которой я столкнулся, заключается в том, что когда я хочу вставить строки в текстовый объект, я получаю неинформативную ошибку и застреваю на все утро.

def transformer_addMemo(fileobj):
    STYLUSMEMO =r"""hellow world"""
    study = fileobj.read()
    location = re.search(r"</BasicOptions>", study)
    print fileobj.name
    print fileobj.mode
    fileobj.seek(0)
    fileobj.write(study[:location.end()] + STYLUSMEMO + study[location.end():])
    return fileobj

и это дает мне

Traceback (most recent call last):
 File "E:\mypy\reg_test\src\preprocessor\preprocessor.py", line 292, in <module>
  main()
 File "E:\mypy\reg_test\src\preprocessor\preprocessor.py", line 288, in main
 filter_identity,
 File "E:\mypy\reg_test\src\preprocessor\preprocessor.py", line 276, in     apply_filter_transformer
   fileobj.writelines(fileobj.readlines())
   IOError: [Errno 0] Error

Если кто-нибудь может дать мне больше информации об ошибке, я был бы очень признателен.

Ответы [ 2 ]

1 голос
/ 29 октября 2009

Невозможно определить причину ошибки из кода, который вы опубликовали. Проблема может быть в протоколе, который вы приняли для своих функций преобразования.

Я немного упросту код:

fileobj = file.open(path, mode)
fileobj = fcn(fileobj)
fileobj.writelines(fileobj.readlines())

Какую гарантию я получаю, fcn возвращает файл, открытый в режиме, в котором был мой исходный файл? Что он возвращает файл, который вообще открыт? Что возвращает файл ? Ну, нет.

Не похоже, что у вас есть основания даже использовать файловые объекты в вашем процессе. Поскольку вы читаете весь файл в память, почему бы просто не заставить ваши функции преобразования принимать и возвращать строки? Итак, ваш код будет выглядеть так:

with open(filename, "r") as f:
    s = f.read()
for transform_function in transforms:
    s = transform_function(s)
with open(filename, "w") as f:
    f.write(s)

Помимо всего прочего, это полностью отделяет часть файлового ввода-вывода вашей программы от части преобразования данных, так что проблемы в одной не влияют на другую.

1 голос
/ 29 октября 2009

Есть удобный модуль Python для изменения или чтения группы файлов: fileinput

Я не уверен, что является причиной этой ошибки. Но вы читаете весь файл в память, что является плохой идеей в вашем случае, потому что файлы потенциально большие. Используя fileinput, вы можете легко заменить файлы. Например:

import fileinput
import sys

for line in fileinput.input(list_of_files, inplace=True):
    sys.stdout.write(line)
    if keyword in line:
         sys.stdout.write(my_text)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...