python - 使用 matplotlib 和 boto 将绘图从内存上传到 s3
Posted
技术标签:
【中文标题】python - 使用 matplotlib 和 boto 将绘图从内存上传到 s3【英文标题】:python - uploading a plot from memory to s3 using matplotlib and boto 【发布时间】:2015-10-07 18:07:54 【问题描述】:这是我的工作脚本,它生成一个绘图,将其保存到本地磁盘,上传到 S3 并删除文件:
plt.figure(figsize=(6,6))
plt.plot(x, y, 'bo')
plt.savefig('file_location')
conn = boto.s3.connect_to_region(
region_name=AWS_REGION,
aws_access_key_id=AWS_ACCESS_KEY_ID,
aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
calling_format=boto.s3.connection.OrdinaryCallingFormat()
)
bucket = conn.get_bucket('bucket_name')
k = Key(bucket)
k.key = 'file_name'
k.set_contents_from_filename('file_location')
os.remove(file_location)
我想要的是跳过磁盘写入并直接从内存中上传情节。
有什么建议可以实现吗?
【问题讨论】:
保存到io.BytesIO()
, f = io.BytesIO(),plt.savefig(f)
太好了,谢谢!之后上传我只需要打电话f.seek(0)
然后k.set_contents_from_file(f)
不用担心。是的,指针在写入后将位于末尾。
【参考方案1】:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_agg import FigureCanvasAgg
import boto3
import io
# some random plotting. We need the figure object later
fig, ax = plt.subplots(1,1,figsize=(6,6))
ax.plot(np.linspace(0,1,50),
np.random.normal(0.5,0.5,50))
canvas = FigureCanvas(fig) # renders figure onto canvas
imdata = io.BytesIO() # prepares in-memory binary stream buffer (think of this as a txt file but purely in memory)
canvas.print_png(imdata) # writes canvas object as a png file to the buffer. You can also use print_jpg, alternatively
s3 = boto3.resource('s3',
aws_access_key_id='your access key id',
aws_secret_access_key='your secret access key',
region_name='us-east-1') # or whatever region your s3 is in
s3.Object('yourbucket','picture.png').put(Body=imdata.getvalue(),
ContentType='image/png')
# this makes a new object in the bucket and puts the file in the bucket
# ContentType parameter makes sure resulting object is of a 'image/png' type and not a downloadable 'binary/octet-stream'
s3.ObjectAcl('yourbucket','picture.png').put(ACL='public-read')
# include this last line if you find the url for the image to be inaccessible
【讨论】:
【参考方案2】:把它们放在一起:
img_data = io.BytesIO()
plt.savefig(img_data, format='png')
img_data.seek(0)
s3 = boto3.resource('s3')
bucket = s3.Bucket(BUCKET_NAME)
bucket.put_object(Body=img_data, ContentType='image/png', Key=KEY)
感谢@padraic-cunningham 和@guyb7 的提示!
【讨论】:
上传的图像对我来说是空的 :( 但我正在尝试上传实际图像,而不是 plt 图……这会有所不同吗? 如何读回图像?我试过 img=skio.imread(io.BytesIO(obj.get()['Body'].read())) 但我得到一个错误:“找不到格式来读取模式'i'中的指定文件" @Raksha 尝试以下操作:将 plt.savefig(img_data, format='png') 替换为 plt.imsave(img_data, my_img) 其中 my_img 是您的图像数据。 如果上传的图片如@Raksha 所述为空。检查这个答案***.com/questions/9012487/… 有谁知道为什么这个解决方案在我使用 AWS signedURL 打开它时会裁剪图?以上是关于python - 使用 matplotlib 和 boto 将绘图从内存上传到 s3的主要内容,如果未能解决你的问题,请参考以下文章
如何在ubuntu上使用pip为python3升级matplotlib?