LINUX.ORG.RU

Использовать переменную из другого цикла

 


0

1

Добрый день. Допиливаю скрипт по переводу субтитров на Python.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import textwrap

i = 0
with open("txt") as f:
    for line in f:
        Line = line.strip()
        print(len(Line), "- длина строки из файла TXT:", Line)
        if i % 2 == 0:
            FirstLine = Line
            LenFirstLine = len(Line)
            print("FirstLine")
            with open("srt") as d:
                for line in d:
	                srt = line.strip()
	                print(srt)
	                print(FirstLine)
	                if srt in FirstLine:
	                    print(srt, " - совпадающая строка")
	                    print(len(srt), "- длина совпадающей строки:", srt)
	                    # Divide_srt_by_LenFirstLine = round(len(srt) / LenFirstLine, 2)
	                    # print(Divide_srt_by_LenFirstLine, "=", "длина:", srt, "/", "длина:", FirstLine)
	                    # ChooseBlockFromSecondLine = round(Divide_srt_by_LenFirstLine * LenSecondLine)
	                    # print(ChooseBlockFromSecondLine, "= ( длина:", srt,
	                    # 	"/ длина:", FirstLine, ") * длина:", SecondLine)
        else:
            SecondLine = Line
            print("SecondLine =", SecondLine)
            LenSecondLine = len(Line)
            print("LenSecondLine - ", LenSecondLine)
        i = i + 1

Нужно использовать переменную LenSecondLine внутри этой длинной конструкции, но она определится только на следующей итерации. Как ее можно определить?

Суть скрипта такая:

Есть файл SRT:

1
00:00:00,239 --> 00:00:03,280
Like most modern PBXs Asterisk supports a 
call queuing feature.

И есть файл TXT:

Like most modern PBXs Asterisk supports a call queuing feature.
Как и большинство современных АТС Asterisk поддерживает управление очередями вызовов функции.

Скрипт берет строку из TXT и сравнивает ее со строками из SRT. Когда скрипт находит сопадение - можно менять на русский текст, но переменная с русским текстом будет на следующей итерации. Как быть?

А сразу весь файл с субтитрами загрузить как список строк и потом уже со списком работать? не вариант? Вроде не должен быть слишком большим этот файл.

ossa ★★ ()
Последнее исправление: ossa (всего исправлений: 1)

Нужно использовать переменную LenSecondLine внутри этой длинной конструкции, но она определится только на следующей итерации. Как ее можно определить?

Если втупую - определи ее как None.

P.S. ГорбатыйКейсДляПеременных - не по феншую.

tailgunner ★★★★★ ()
Последнее исправление: tailgunner (всего исправлений: 1)

Ты ничерта не умеешь в питон. Суть питонокодинга-на-коленке — в структурах данных.

Ты на каждую строку первого файла пытаешься прочитать второй файл заново. Зачем?

Пройди свой txt полностью, сделай словарь Англ→Рус из него. Потом пройди свой txt, используя этот словарь для замены английской фразы на русскую.

Сейчас у тебя O(n²), что мягко говоря фигово.

Ещё я не совсем понимаю, почему ты пытаешься учитывать длину каждой строки (разве не у всех строк перенос в одном месте?), но с этим алгоритмом пофиг и можешь делать и так.

Как-нибудь вроде

en2rus = {}
with open("txt") as f:
  try:
    while True:
      firstLine = next(f)
      secondLine = next(f)
      en2rus[firstLine] = secondLine  # можно заодно любую длину сюда закинуть
  except StopIteration:
    pass  # файл кончился   
и после этого уже делать что угодно с твоим en2rus.

x3al ★★★★★ ()
Ответ на: комментарий от x3al

Вот именно, что не у всех строк перенос в одном месте. Пример хорош, если строки одинаковой длины. Но в субтитрах такого не бывает. Они мало того что разной длинны, так и еще и одна фраза может быть на 2-3-4-5 строках....

chemtech ()
Ответ на: комментарий от chemtech

Python-way, первая строка в гугле.

Мой костыль с двойным next() — не слишком Python-way но сойдёт.

x3al ★★★★★ ()
Ответ на: комментарий от chemtech

Запихни в словарь вместе с переводом свою длину.

Вообще, это — проход файла с переводом.

В разной длине субтитров есть особый смысл? Тем более в вычислении длины в символах, а не в пикселях (у тебя же не моноширинный шрифт)?

2-3-4 строки могут быть для удобства чтения, но это удобство зависит от языка т.е. тебе может понадобиться разбить в другом месте.

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

x3al ★★★★★ ()
Ответ на: комментарий от x3al

Сделал скрипт. Разделил английский текст и русский перевод отдельно. Но теперь у меня стоит проблема замены.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import textwrap

i = 0
with open("eng") as f:
    for line in f:
        Line = line.strip()
        print(len(Line), "- длина строки из файла TXT:", Line)
        print("-" * 60)
        if i % 2 == 0:
            FirstLine = Line
            LenFirstLine = len(Line)
            print("i =", i)
            print("FirstLine")
            print("-" * 60)
            with open("srt") as d:
                for line in d:
                    srt = line.strip()
                    print(srt)
                    print(FirstLine)
                    if srt in FirstLine:
                        print("-" * 60)
                        print(srt, " - совпадающая строка")
                        print(len(srt), "- длина совпадающей строки:", srt)
                        print("-" * 60)
                        with open("rus") as k:
                            for string in k:
                                RusLine = string.strip()
                                LenRusLine = len(RusLine)
                                print(
                                    len(RusLine), "- длина строки из файла TXT:", RusLine)
                                print("-" * 60)
                                Divide_srt_by_LenFirstLine = round(
                                    len(srt) / LenFirstLine, 2)
                                print(Divide_srt_by_LenFirstLine, "=",
                                      "длина:", srt, "/", "длина:", FirstLine)
                                print("-" * 60)
                                ChooseBlockFromSecondLine = round(
                                    Divide_srt_by_LenFirstLine * LenRusLine)
                                print(ChooseBlockFromSecondLine, "= ( длина:", srt,
                                      "/ длина:", FirstLine, ") * длина:", LenRusLine)
                                print("КОНЕЦ")
                                print(srt)
                                for y in textwrap.wrap(RusLine, width=ChooseBlockFromSecondLine):
                                    print(y)
                                d.write( line.replace( srt, y ) )
        i = i + 1
Вываливается с ошибкой:
    d.write( line.replace( srt, y ) )
io.UnsupportedOperation: not writable
Как лучше текст заменить?

chemtech ()
Ответ на: комментарий от chemtech

Определись, что ты хочешь — читать или писать файл.

with open(«srt») as d:

Здесь ты открываешь только для чтения.

Открой другой файл для записи («w», читай док по open()), запиши в него, замени им исходный файл. Другие способы чреваты.

x3al ★★★★★ ()
Ответ на: комментарий от chemtech

И да, прекрати вкладывать циклы друг в друга.

with open(«rus») as k:
for string in k:

Тут ты заново открываешь свой rus столько раз, сколько строк в en.

Ну и получаешь сложность O(n³), не говоря о бреде вместо результата. На ровном месте.

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

x3al ★★★★★ ()
Ответ на: комментарий от x3al

Это первый мой скрипт на Python. Попробую. Но пока непонимаю как это реализовать. Про это: «сначала прочитай один файл и запихни нужную информацию в структуру (хотя бы в словарь), потом открывай второй.»

chemtech ()
Ответ на: комментарий от x3al

Точнее не первый. Первые былы простые из книги Michael Dawson - «Программируем на Python»

chemtech ()
Ответ на: комментарий от x3al

Пытаюсь вот так заменить

new_file = open(translate, 'w')
new_file.write(line.replace(srt, y))
new_file.close()

Ругается

    new_file = open(translate, 'w')
NameError: name 'translate' is not defined

chemtech ()
Ответ на: комментарий от chemtech
en2rus = {}
with open("txt") as f:
  try:
    while True:
      firstLine = next(f)
      secondLine = next(f)
      en2rus[firstLine] = secondLine  # можно заодно любую длину сюда закинуть
  except StopIteration:
    pass  # файл кончился   
with open("srt") as in, open("srt-out", "w") as out:
  for line in in:
    pass  # сделать что-то со строкой и записать её в out. Можно использовать en2rus.

Естественно, отступы важны. У тебя второй цикл — вложен в первый, не делай так без надобности.

x3al ★★★★★ ()
Последнее исправление: x3al (всего исправлений: 1)
Ответ на: комментарий от chemtech

Потому, что без кавычек.

Если ты делаешь именно так, как написал — ты запишешь ровно 1 строку. Потом перезапишешь её. Много раз. Точнее, число_строк_в_rus * строк_в_en * строк_в_srt раз. Вытащи open() из цикла, при желании — в with, если лень закрывать.

x3al ★★★★★ ()
Ответ на: комментарий от x3al

Посмотрел ваш скрипт. Согласен для файла с английскими и русскими строками.

Но как быть с файлом субтитров.

1
00:00:00,239 --> 00:00:03,280
Like most modern PBXs Asterisk supports a 
call queuing feature.


Они имеют разную длину..
chemtech ()
Ответ на: комментарий от anonymous

Причастись к гвидосвященной PEP-8, безбожник.

Deleted ()
Ответ на: комментарий от x3al

Добрый день.

Переделал немного скрипт:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import textwrap

# Создаем словать
en2rus = {}
# Открываем файл c переводами
with open("txt") as f:
    # Если открывается
    try:
        # Обрабаываем в цикле
        while True:
            # Первая строка
            FirstLine = next(f)
# Вторая строка
            SecondLine = next(f)
# Заносим первую строку как ключ в словарь, а вторую строку как значение в
# словарь
            # можно заодно любую длину сюда закинуть
            en2rus[FirstLine] = SecondLine
# Обрабатываем ошибку
    except StopIteration:
        pass  # файл кончился

with open("srt") as b, open("srt-out", "w") as out:
    for SrtLine in b:
        for key in en2rus:
            if SrtLine in key:               
                print(SrtLine)

Почему- то берет последнее значение. Хотя srt имеет вид:

1
00:00:00,239 --> 00:00:03,280
Like most modern PBXs Asterisk supports a 
call queuing feature.
chemtech ()
Ответ на: комментарий от x3al

Переделал немного скрипт. Но еще есть ошибки. Пример. Вот есть вот такой файл srt:

1
00:00:12,753 --> 00:00:14,762
Agreed.
What's your point?
2
00:00:14,950 --> 00:00:18,140
There's no point, I just think
it's a good idea for a T-shirt.

Вот что получается:

1
00:00:12,753 --> 00:00:14,762
Согласе
смысл?
2
00:00:14,950 --> 00:00:18,140
Нет смысла, я всего лишь
подумал, это хорошая идея для
Сам скрипт
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import textwrap

# Создаем словать
en2rus = {}
# Открываем файл c переводами
with open("txt") as f:
    # Если открывается
    try:
        # Обрабаываем в цикле
        while True:
            # Первая строка
            FirstLine = next(f)
# Вторая строка
            SecondLine = next(f)
# Заносим первую строку как ключ в словарь, а вторую строку как значение в
# словарь
            # можно заодно любую длину сюда закинуть
            en2rus[FirstLine] = SecondLine
            # print(en2rus)
# Обрабатываем ошибку
    except StopIteration:
        pass  # файл кончился

# Открываем файл c переводами
with open("srt") as b, open("srt-out", "w") as out:
    # Если открывается
    try:
        # Обрабаываем в цикле
        while True:
            # Первая строка
            FirstLine = next(b)
            # Номер блока субтитров. Просто записываем
            out.write(FirstLine)
            # Вторая строка. Время субтитра. Просто записываем
            SecondLine = next(b)
            out.write(SecondLine)
            # Третья строка
            ThirdLine = next(b)
            # Убираем знак завершения строки
            SrtLine = ThirdLine.rstrip('\r\n')
            # Перебираем все ключи словаря
            for key in en2rus:
                # Проверяем входит ли строка в ключи словаря - ключи словаря английский текст
                if SrtLine in key:
                    # Определяем длину ключа
                    Lenkey = len(key)
                    # Определяем длину строки
                    LenSrtLine = len(SrtLine)
                    # Определяем длину переведенной строки, от которой нужно отрезать текст
                    y = textwrap.wrap(en2rus[key], width=LenSrtLine)
                    # Заменяем английский текст на перевод
                    ReplaceLine = ThirdLine.replace(SrtLine, y[0])
                    # Записываем замененный текст
                    out.write(ReplaceLine)
            # Четвертая строка
            FourthLine = next(b)
            # Убираем знак завершения строки
            SrtLine = FourthLine.rstrip('\r\n')
            # Если длина строки = 2, тогда просто записываем
            if len(SrtLine) == 2:
                out.write(FourthLine)
            else:
                # Иначе:
                # Перебираем все ключи словаря
                for key in en2rus:
                    # Проверяем входит ли строка в ключи словаря - ключи словаря английский текст
                    if SrtLine in key:
                        # Определяем длину ключа
                        Lenkey = len(key)
                        # Определяем длину строки
                        LenFourthLine = len(SrtLine)
                        # Определяем длину переведенной строки, от которой нужно отрезать текст
                        y = textwrap.wrap(en2rus[key], width=LenSrtLine)
                        # Заменяем английский текст на перевод
                        ReplaceLine = FourthLine.replace(SrtLine, y[1])
                        # Записываем замененный текст
                        out.write(ReplaceLine)
# Обрабатываем ошибку
    except StopIteration:
        pass  # файл кончился

Как исправить?

chemtech ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.