В чем ошибки получения информации из потока и в преобразовании форматов?

from threading import Thread
data_from_file=[]

def thread_read (file_name):
    with open(file_name, 'r',encoding="utf-8") as f:
        str1=f.read()
        f.close
        data_from_file.append(str1)
    return

if __name__ == "__main__":
    file_r="read_thread.txt"
    new_th1=Thread (target=thread_read,args=(file_r,))
    new_th1.start()
    input()   
    str_r=str(data_from_file)
    print('str_r:', str_r)

С удовольствием изучаю Python. В учебной задаче столкнулся с непонятным поведением моего скрипта. Уже несколько часов копаюсь, отладкой конкретизировал проблему, но дальше застрял. Просьба помочь:

  • Почему скрипт работает относительно верно, только если ввести искусственную задержку - input()? (что нужно вместо задержки или хоть что я не изучил? :-)

  • Я вообще правильный метод для возвращения результата из потока выбрал через внешнюю переменную? (Ввел список для возвращения, так как в StackOverflow на вопрос, как передать результат потока в main, советовали (не мне) такой подход.)

  • Обновление: Этот вопрос отвечен ниже:"Почему даже при правильной работе финальный результат при печати строки получается не: 'Тест', а ['Тест']?" Спасибо Эникейщику!

Детали:

  • Задача: чтение из файла потоком, возврат результата в main.

  • Файл read_thread содержит слово "Тест".

  • Поставил отладочную печать print и отладочный input: если запускать без input, то результат отладочной печати - неверный: str_r: [] если запускать c input, то вернее: str_r: ['Тест']


Ответы (1 шт):

Автор решения: Roman-Stop RU aggression in UA

Например, используя ThreadPoolExecutor и Future:

from concurrent.futures import ThreadPoolExecutor

def thread_read(file_name):
    with open(file_name, 'r', encoding="utf-8") as f:
        return f.read()

if __name__ == "__main__":
    file_r="read_thread.txt"
    with ThreadPoolExecutor() as executor:
        future = executor.submit(thread_read, file_r)  
        # тут будет ожидание, пока thread_read не сделает return
        # и это значение вернет result()
        str_r=future.result()
    print('str_r:', str_r)

Или чисто потоками:

from threading import Thread

def thread_read(file_name, value_holder):
    with open(file_name, "r", encoding="utf-8") as f:
        value_holder[0] = f.read()

if __name__ == "__main__":
    file_r = "read_thread.txt"
    result_holder = [None]
    new_th1 = Thread(target=thread_read, args=(file_r, result_holder))
    new_th1.start()
    # далее ключевой момент - ждем когда new_th1 закончит выполнение
    new_th1.join()
    print("str_r:", result_holder[0])

Я вообще правильный метод для возвращения результата из потока выбрал через внешнюю переменную

Этот способ плох тем, что требует использования глобальной переменной. Лучше как во втором примере, а еще лучше использовать более высокоуровневые средства как Future или Queue.

→ Ссылка