Почему мой Python async / await на самом деле не пишет файлы matplotlib? - PullRequest
0 голосов
/ 15 февраля 2019

Мой код:

import os
import h5py
import asyncio
import numpy as np
import matplotlib.pyplot as plt
from dotenv import load_dotenv
load_dotenv()

data_path = os.environ['DATA_PATH']
output_data_path = os.environ['OUTPUT_DATA_PATH']
patient_files = os.listdir(data_path)


async def save_file(filename, image_data):
    plt.imshow(image_data, cmap='gray')
    await plt.savefig(filename, pad_inches=0, bbox_inches='tight')

for patient_file in patient_files:
    patient_parts = patient_file.split('.')
    patient_parts = patient_parts[0].split('_')
    patient_id = patient_parts[1]
    if int(patient_id) < 21:
        continue
    print('Doing patient', patient_id)

    patient_data = h5py.File(os.path.join(data_path, patient_file))
    variables = patient_data.items()

    for var in variables:
        name = var[0]
        data = var[1]

        if type(data) is h5py.Dataset:
            value = data.value
            plt.axis('off')
            if name == 'Svar25':
                for layer in range(value.shape[0]):
                    output_file = os.path.join(
                        output_data_path, patient_id + '_FLAIR_debone_' + str(layer) + '.png')
                    save_file(filename=output_file, image_data=value[layer])

            if name == 'Svar24':
                for layer in range(value.shape[0]):
                    output_file = os.path.join(
                        output_data_path, patient_id + '_FLAIR_bone_' + str(layer) + '.png')
                    save_file(filename=output_file, image_data=value[layer])

Я пытаюсь записать свои файлы асинхронно, но на самом деле это не запись.

Что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 16 февраля 2019

Что я делаю не так?

await plt.savefig(filename, pad_inches=0, bbox_inches='tight')

Функция не становится асинхронной только потому, что перед ней используется await.Вам необходимо объявить функцию как async def, чтобы сделать ее асинхронной в первую очередь.

Любая функция, которая использует await, должна быть определена как async def до точки входа вашегопрограмма (например, async def main()).Вам нужно запустить точку входа в цикле событий , чтобы заставить работать асинхронный код.

Обе функции plt.imshow и plt.savefig синхронизированы по своей природе.Вы можете попробовать привести вторую к асинхронности, используя run_in_executor и ожидая результата, но я не уверен, будет ли он работать.Я также не уверен, что вам это нужно: вы, вероятно, не достигнете ускорения при параллельном выполнении операций ввода-вывода.


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

0 голосов
/ 15 февраля 2019

Вы забыли добавить await перед save_file(...).Это означает, что цикл asyncio никогда не будет планировать функцию записи файла.

Очень распространенная ошибка в моем опыте ...

Обновление: из вашего комментария кажется, что вы никогда не запускаете цикл asyncio дляфункции процесса.Вам нужно будет запустить функцию верхнего уровня согласно документам .В Python 3.7 появился приятный новый простой синтаксис, принцип тот же, что и в 3.5 и 3.6, но немного более сложный.

>>> import asyncio

>>> async def main():
...     print('hello')
...     await asyncio.sleep(1)
...     print('world')

>>> asyncio.run(main())
hello
world
...