проблема записи в файл в итераторе "for line in" в скрипте Python - PullRequest
0 голосов
/ 23 февраля 2010

Кажется, это довольно неловкий вопрос, но после дня прочтения инструкций и руководств его нужно задать.

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

Я создал тестовый скрипт, который, как мне казалось, будет имитировать поведение, но он ведет себя отлично:

for i in range(10):
    f = open('output.txt','w')

    f.write( "---------------------------\n" )

    FILE1 = open('test1.txt','r')
    for line in FILE1:
        f.write( "... compliments of loop #1 ...\n" )
        f.write( line )
    FILE1.close()

    f.write( "\n##########################\n" )

    FILE2 = open('test2.txt','r')
    for line in FILE2:
        f.write( "... compliments of loop #1 ...\n" )
        f.write( line )
    FILE2.close()

    f.write( "\n++++++++++++++++++++++++++\n" )

Выходные данные соответствуют ожидаемым: статические строки чередуются со скопированными строками. Мой настоящий, уродливый сценарий, однако, не делает этого. Я не хочу вставлять сюда все это, но включу столько, сколько считаю нужным (и я, вероятно, тоже ошибусь, потому что не знаю, что происходит). Он ссылается на массив объектов - я не буду включать класс, как он себя ведет.

for i in range(10):
    print "script-%s-%i-%s%s" % (cities[i].user,i,cities[i].name,cities[i].coords)

    f = open("script-%s-%i-%s%s" % (cities[i].user,i,cities[i].name,cities[i].coords),'w')

    f.write( "//\n" )
    f.write( "//\n// %s - %s            %s\n" % (cities[i].user,cities[i].name,cities[i].coords) )
    f.write( "//\n" )
    f.write( "//\n" )

    npc10 = open("script-%s-npc10-%i.txt" % (cities[i].user,i),'r')
    for line in npc10:
        f.write( "ifgosub ( m_city.AnyIdleHero(%s) == false ) wait_for_big_hero\n" % (cities[i].hero) )
        f.write( "ifgosub ( m_city.IsArmyReady(a:%i,s:%i,w:%i,wo:%i) == false ) gosub check_npc10\n" % (lvl10.arch,lvl10.scout,lvl10.warr,lvl10.work) )
        f.write( "ifgosub ( m_city.IsArmyReady(a:%i,s:%i,w:%i,wo:%i) == false ) farm_npc5\n" % (lvl10.arch,lvl10.scout,lvl10.warr,lvl10.work) )
        f.write( "ifgosub ( m_city.AnyIdleHero(%s) == false ) wait_for_big_hero\n" % (cities[i].hero) )
        f.write( line )
    npc10.close()

    f.write( "\n//\n" )
    f.write( "label farm_npc5\n" )

    npc5 = open("script-%s-npc5-%i.txt" % (cities[i].user,i),'r')
    for line in npc5:
        f.write( "sleep 5\n" )
        f.write( line )
    npc5.close()

    f.write( "\n//\n" )
    # ... 107 lines of static f.write's

    f.close()

Пример одного из входных файлов (script-%s-npc10-%i.txt" % (cities[i].user,i)) - все они очень похожи:

атака 456,357 Альфред а: 9215, т: 185, ш: 200, ш: 2000, с: 200 // Расстояние: 1 Время полета: 8 м 52 с
атака 159,357 Альфред а: 9215, т: 185, ш: 200, ш: 2000, с: 200 // Расстояние: 1 Время полета: 8 м 52 с
атака 159,215 Альфред а: 9215, т: 185, ш: 200, ш: 2000, с: 200 // Расстояние: 1 Время полета: 12 м 34 с

Пример одного из выходных файлов
("script-%s-%i-%s%s" % (cities[i].user,i,cities[i].name,cities[i].coords)):

//
// user1 - cityname1 (456,456)
//
//
ifgosub (m_city.AnyIdleHero (Alfonso) == false) wait_for_big_hero
ifgosub (m_city.IsArmyReady (a: 92150, с: 2000, w: 2000, wo: 2000) == false) gosub check_npc10
ifgosub (m_city.IsArmyReady (a: 92150, s: 2000, w: 2000, wo: 2000) == false) farm_npc5
ifgosub (m_city.AnyIdleHero (Alfonso) == false) wait_for_big_hero
атака 456,357 Альфред а: 9215, т: 185, ш: 200, ш: 2000, с: 200 // Расстояние: 1 Время полета: 8 м 52 с
атака 159,357 Альфред а: 9215, т: 185, ш: 200, ш: 2000, с: 200 // Расстояние: 1 Время полета: 8 м 52 с
атака 159,215 Альфред а: 9215, т: 185, ш: 200, ш: 2000, с: 200 // Расстояние: 1 Время миссии: 12 м 34 с
//
ярлык farm_npc5
сон 5
атака 354,159 Альфред b: 50, т: 40 // Расстояние: 1 Время миссии: 13 м 20 с
атака 789,654 Альфред b: 50, т: 40 // Расстояние: 2 Время полета: 26 м 40 с
атака 125 456 Альфреда b: 50, t: 40 // Расстояние: 2 Время полета: 29 м 48 с
//
[...]

Какая разница? Почему статические строки не повторяются, в то время как скопированные строки повторяются?

ОТВЕТ: Я написал исходные файлы в OSX TextEdit, поэтому их символ новой строки был '\r', как указано gnibbler . Следование его примеру привело меня к 6 PEP 278: Универсальная поддержка Newline . Используя режим файла 'rU' все в квадрате.

Спасибо, ребята!

Ответы [ 4 ]

1 голос
/ 23 февраля 2010

Используя пример, который вы дали в качестве входного файла, и составленную переменную city + lvl10, скрипт работает как положено: для каждой из строк «атаки» на входе сначала печатается несколько строк «ifgosub», а затем линия "атаки".

Наиболее вероятной причиной вашей проблемы является то, что итерация по файлу не дает вам строки отдельно, а все строки одновременно. В моих экспериментах это происходило, если я решил использовать CR (\ r) в качестве символов конца строки (это соглашение использовалось в MacOS до версии 9.x). Возможно, некоторые странные кодировки символов для входных файлов могут вызвать аналогичную проблему.

Чтобы проверить это предположение, просто попробуйте перебрать один из ваших файлов, возможно, так:

i = 0
npc10 = open("script-%s-npc10-%i.txt" % (cities[i].user,i),'r')
lines = [line for line in npc10]
npc10.close()

после этого вы можете проверить len(lines), если оно больше 1.

Кстати, начиная с Python 2.6 (или 2.5 + from __future__ import with_statement), вы можете использовать контекстные менеджеры, чтобы обеспечить закрытие файлов:

with open("script-%s-npc10-%i.txt" % (cities[i].user,i),'r') as npc10:
    for line in npc10:
        #....
    # the file gets closed automatically after the with-statement
1 голос
/ 23 февраля 2010

Похоже, что цикл for выполняется только один раз.

Я не уверен, почему это будет сделано - возможно, есть проблема с окончаниями строк, поэтому весь файл читается как одна строка.

Например, если строки входного файла сценария имеют \r окончание строки и python ожидает \n окончание строки.

Попробуйте использовать 'rU' в качестве режима вместо 'r'

0 голосов
/ 23 февраля 2010

Возможно, вы перепутали табуляцию и пробелы в вашем файле, и поэтому отступ не такой, как кажется. Попробуйте установить флажок -t в python для проверки непоследовательного использования вкладок:

python -t script.py
0 голосов
/ 23 февраля 2010

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

Не уверен, но возможной причиной может быть смешивание файлов Windows / Linux и интерпретаторов python ("\ r \ n" vs "\ n" Кодировки конца строки ), но кто-то может исправить я здесь.

Общий совет при смешивании текстовых файлов Linux / Windows: конвертируйте ваши файлы с помощью dos2unix или unix2dos инструментов командной строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...