Вы не можете напрямую загрузить файл в Google Cloud Storage с помощью функции python open
(которая используется matplotlib.pyplot.savefig
за кулисами). Вместо этого вам следует использовать клиентскую библиотеку Cloud Storage для Python . Обратитесь к этой документации для подробностей о том, как эта библиотека используется. Это, среди прочего, позволит вам манипулировать файлами и загружать / скачивать их в GCS.
Вам нужно будет импортировать эту библиотеку, чтобы использовать ее, вы можете установить ее, запустив pip install google-cloud-storage
и импортировать ее как from google.cloud import storage
.
Кроме того, поскольку plt.figure
является объектом, а не фактическим изображением .png
, которое вы хотите загрузить, вы также не можете напрямую загрузить его в Google Cloud Storage.
Однако вы можете выполнить одно из следующих действий:
Вариант 1 : сохранить изображение локально, а затем загрузить его в облачное хранилище Google:
[1118 ] Используя ваш код:
from google.cloud import storage
def saving_figure(path_logdir):
data = np.arange(0, 21, 2)
fig = plt.figure(figsize=(20, 10))
plt.plot(data)
fig.savefig("your_local_path/accuracy_loss_graph.png".format(path_logdir))
plt.close()
# init GCS client and upload file
client = storage.Client()
bucket = client.get_bucket('skin_cancer_mnist')
blob = bucket.blob('logs/20190116-195604/accuracy_loss_graph.png') # This defines the path where the file will be stored in the bucket
your_file_contents = blob.upload_from_filename(filename="your_local_path/accuracy_loss_graph.png")
Вариант 2 : сохраните результат изображения из рисунка в переменную, затем загрузите его в GCS в виде строки (из байтов):
Я нашел следующий ответ StackOverflow, который, кажется, сохраняет изображение фигуры в байтовую строку .png
, однако сам не пробовал.
Опять же, основываясь на вашем коде:
from google.cloud import storage
import io
import urllib, base64
def saving_figure(path_logdir):
data = np.arange(0, 21, 2)
fig = plt.figure(figsize=(20, 10))
plt.plot(data)
fig_to_upload = plt.gcf()
# Save figure image to a bytes buffer
buf = io.BytesIO()
fig_to_upload.savefig(buf, format='png')
buf.seek(0)
image_as_a_string = base64.b64encode(buf.read())
# init GCS client and upload buffer contents
client = storage.Client()
bucket = client.get_bucket('skin_cancer_mnist')
blob = bucket.blob('logs/20190116-195604/accuracy_loss_graph.png') # This defines the path where the file will be stored in the bucket
your_file_contents = blob.upload_from_string(image_as_a_string, content_type='image/png')
Редактировать : Оба варианта предполагают, что среда, из которой вы запускаете скрипт, имеет Cloud SDK установлена и активирована учетная запись с аутентификацией в Google Cloud (если у вас ее нет, вы можете проверить эту документацию , в которой объясняется, как это сделать).
Вы можете попробовать файл с отображением в память .
Этот дает более подробные пошаговые инструкции.
Хотя Windows поддерживает разделяемую память через API-интерфейс отображения файлов , вы не можете легко внедрить отображение общей памяти непосредственно в другой процесс, поскольку MapViewOfFileEx не принимает аргумент процесса.
Однако вы можете ввести некоторые данные, выделив память в другом процессе, используя VirtualAllocEx и WriteProcessMemory . Если вы должны были скопировать в дескриптор, используя DuplicateHandle , а затем внедрить заглушку, которая вызывает MapViewOfFileEx , вы могли бы установить отображение совместно используемой памяти в другом процессе. Поскольку, похоже, вы все равно будете вводить код, это должно сработать для вас.
Подводя итог, вам необходимо:
Вам может показаться немного проще, если ваша заглушка загружает внешнюю библиотеку, то есть просто вызовите LoadLibrary (поиск адреса LoadLibrary оставлен в качестве упражнения для читателя) и выполните свою работу из точка входа библиотеки dllmain. В этом случае использование именованной совместно используемой памяти, вероятно, будет проще, чем работа с DuplicateHandle. См. Статью MSDN о CreateFileMapping для получения более подробной информации, но, по сути, передайте INVALID_HANDLE_VALUE для hFile и имя для lpName.
Редактировать : Так как ваша проблема заключается в передаче данных, а не в фактическом внедрении кода, вот несколько вариантов.
Редактировать 2 : вот эскиз того, как вы могли бы реализовать хранение дескриптора или указателя для своей заглушки:
.db B8 ;; mov eax, imm32
.dl handle_value ;; fill this in (located at the start of the image + one byte)
;; handle value is now in eax, do with it as you will
;; more code follows...
Вы также можете просто использовать фиксированное имя, которое вероятно, проще.
Вы можете попробовать использовать Boost.Interprocess для связи между двумя процессами. Но чтобы внедрить код в ранее существующее, не поддерживаемое программное обеспечение, вам, вероятно, придется использовать способ @ bdonlan, используя WriteProcessMemory .
Если вы говорите о Windows, то основным препятствием является то, что каждый процесс находится в своем собственном виртуальном адресном пространстве. К сожалению, вы не можете передавать обычные адреса памяти от процесса к процессу и получать ожидаемые результаты. (С другой стороны, все потоки находятся в одном адресном пространстве, поэтому потоки могут видеть память одинаково.)
Windows, однако, имеет общее пространство памяти, к которому вы должны быть очень осторожны. управлять правильно. Любой процесс, который выделяет пространство в общем пространстве памяти, явно отвечает за освобождение этой памяти. Это контрастирует с локальной памятью, которая более или менее исчезает, когда процесс умирает.
См. этот образец статьи MSDN для некоторых идей о том, как вы можете использовать пространство разделяемой памяти, чтобы захватить мир. Эээ, интерфейс с устаревшим программным обеспечением. Или что угодно :) Удачи в любом деле!