繁体   English   中英

Python 3: How to upload a pandas dataframe as a csv stream without saving on disc?

[英]Python 3: How to upload a pandas dataframe as a csv stream without saving on disc?

我想将 pandas dataframe 作为 csv 文件上传到服务器而不将其保存在光盘上。 有没有办法创建一个或多或少的“假 csv”文件,它假装是一个真实的文件?

这是一些示例代码:首先,我从 sql 查询中获取数据并将其存储为 dataframe。 在upload_ga_data function 我想有这个逻辑的东西

 media = MediaFileUpload('df',
                      mimetype='application/octet-stream',
                      resumable=False)

完整示例:

from __future__ import print_function
from apiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
from googleapiclient.errors import HttpError
from apiclient.http import MediaFileUpload
import pymysql
import pandas as pd
con = x

ga_query = """
    SELECT XXXXX
    """

df = pd.read_sql_query(ga_query,con)

df.to_csv('ga_export.csv', sep=',', encoding='utf-8', index = False)

def upload_ga_data():
    try:
        media = MediaFileUpload('ga_export.csv',
                          mimetype='application/octet-stream',
                          resumable=False)
        daily_upload = service.management().uploads().uploadData(
                accountId=accountId,
                webPropertyId=webPropertyId,
                customDataSourceId=customDataSourceId,
                media_body=media).execute()
        print ("Upload was successfull")
    except TypeError as error:
      # Handle errors in constructing a query.
      print ('There was an error in constructing your query : %s' % error)

使用可以实现所需的行为:

创建一个或多或少的“假csv”文件,假装是一个真正的文件

Python使文件描述符 (带有open )和 (带有io.StringIO )的行为类似。 然后,您可以使用文件描述符的任何地方也可以使用字符串流。

创建文本流的最简单方法是使用open(),可选择指定编码:

 f = open("myfile.txt", "r", encoding="utf-8") 

内存中的文本流也可用作StringIO对象:

 f = io.StringIO("some initial text data") 

文本流API在TextIOBase的文档中有详细描述。

在Pandas中,您可以使用其签名中具有path_or_buf参数的任何函数来执行此操作,例如to_csv

DataFrame.to_csv( path_or_buf =None, sep=', ', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, mode='w', encoding=None, compression=None, quoting=None, quotechar='"', line_terminator='\\n', chunksize=None, tupleize_cols=None, date_format=None, doublequote=True, escapechar=None, decimal='.')

以下代码将CSV格式的伪数据帧导出为字符串流(非物理文件,内存中的八位字节流):

import io
import pandas as pd

df = pd.DataFrame(list(range(10)))

stream = io.StringIO()
df.to_csv(stream, sep=";")

如果您想要访问流内容,只需发出:

>>> stream.getvalue()
';0\n0;0\n1;1\n2;2\n3;3\n4;4\n5;5\n6;6\n7;7\n8;8\n9;9\n'

它返回内容而无需使用真实文件。

尽管另一个答案是一个很好的开始,但可能有些人对如何完成 op 的整个任务感到困惑。 Here is a way to go from writing a dataframe to a stream to preparing that stream for upload using Google apiclient.http module. 与 op 尝试的一个主要区别是我将 stream 本身传递给 MediaIOBaseUpload 而不是 MediaFileUpload。 该文件被假定为 utf-8 就像 OP 的文件一样。 这对我来说运行良好,直到媒体被上传,然后我有一个错误“ self._fp.write(s.encode('ascii', 'surrogateescape')) UnicodeEncodeError: 'ascii' codec can't encode character '\ position 2313 中的 xe9':序号不在范围内 (128)"

import io
import pandas as pd
from googleapiclient.errors import HttpError

from apiclient.http import MediaIOBaseUpload  # Changed this from MediaFileUpload

df = pd.DataFrame(list(range(10)))

stream = io.StringIO()
# writing df to the stream instead of a file:
df.to_csv(stream, sep=',', encoding='utf-8', index = False)
try:
    media = MediaIOBaseUpload(stream,
                          mimetype='application/octet-stream',
                          resumable=False)

#### Your upload logic here using media just created ####

except HttpError as error:

    #### Handle your errors in uploading here ####

因为我有一个 unicode 字符,所以我开发了替代代码,它完成了同样的事情,但可以处理 unicode 字符。

import io
import pandas as pd
from googleapiclient.errors import HttpError

from apiclient.http import MediaIOBaseUpload  # Changed this from MediaFileUpload

df = pd.DataFrame(list(range(10)))

records = df.to_csv(line_terminator='\r\n', index=False).encode('utf-8')
bytes = io.BytesIO(records)

try:
    media = MediaIOBaseUpload(bytes,
                          mimetype='application/octet-stream',
                          resumable=False)

#### Your upload logic here using media just created ####

except HttpError as error:

    #### Handle your errors in uploading here ####

我用了:

from googleapiclient.http import MediaIoBaseUpload

与@Katherine 相比:

from apiclient.http import MediaIOBaseUpload 

但除此之外,@Katherine 的替代解决方案非常适合我,因为我正在开发一种解决方案,将 dataframe 写入从 Google Cloud Z86408593C34AF727FDD90DF932FZ8B 运行的 Google Drive 中的 csv 文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM