无法解析使用Flask上传的.csv文件

Shi*_*dra 12 python csv flask

我正在尝试上传CSV文件,对其进行处理以生成结果,然后回写(下载)包含结果的新CSV文件.我是Flask的新手,我无法获得一个"正确"的csv.reader对象来迭代和处理.这是到目前为止的代码,

__author__ = 'shivendra'
from flask import Flask, make_response, request
import csv

app = Flask(__name__)

def transform(text_file_contents):
    return text_file_contents.replace("=", ",")


@app.route('/')
def form():
    return """
        <html>
            <body>
                <h1>Transform a file demo</h1>

                <form action="/transform" method="post" enctype="multipart/form-data">
                    <input type="file" name="data_file" />
                    <input type="submit" />
                </form>
            </body>
        </html>
    """

@app.route('/transform', methods=["POST"])
def transform_view():
    file = request.files['data_file']
    if not file:
        return "No file"

    file_contents = file.stream.read().decode("utf-8")
    csv_input = csv.reader(file_contents)
    print(file_contents)
    print(type(file_contents))
    print(csv_input)
    for row in csv_input:
        print(row)

    result = transform(file_contents)

    response = make_response(result)
    response.headers["Content-Disposition"] = "attachment; filename=result.csv"
    return response

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5001, debug=True)
Run Code Online (Sandbox Code Playgroud)

终端输出正在

127.0.0.1 - - [12/Oct/2015 02:51:53] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [12/Oct/2015 02:51:59] "POST /transform HTTP/1.1" 200 -
4,5,6
<class 'str'>
<_csv.reader object at 0x105149438>
['1']
['', '']
['2']
['', '']
['3']
[]
['4']
['', '']
['5']
['', '']
['6']
Run Code Online (Sandbox Code Playgroud)

我读的文件是

在此输入图像描述

当我迭代csv.reader对象时,没有得到代表2行的2个列表,我做错了什么?

iLo*_*Tux 45

好的,所以你的脚本有一个主要问题,csv.reader这里所说,需要一个文件对象或至少一个支持迭代器协议的对象.您正在传递一个str实现迭代器协议的方法,但它不是遍历这些行,而是遍历字符.这就是你有输出的原因.

首先,它给出了一个单一的字符1,它csv.reader看起来像是一个字段的线.在那之后,str给出另一个单个字符,,其csv.reader被视为具有两个空字段的行(因为逗号是字段分隔符).它一直str持续到它耗尽.

解决方案(或至少一个解决方案)是将其str转换为类似文件的对象.我尝试使用提供的流flask.request.files["name"],但不会遍历这些行.接下来,我尝试使用a cStringIO.StringIO,这似乎有类似的问题.我最后在这个问题上提出了一个有效io.StringIO的通用换行模式.我最终得到了以下工作代码(也许它可能更好):

__author__ = 'shivendra'
from flask import Flask, make_response, request
import io
import csv

app = Flask(__name__)

def transform(text_file_contents):
    return text_file_contents.replace("=", ",")


@app.route('/')
def form():
    return """
        <html>
            <body>
                <h1>Transform a file demo</h1>

                <form action="/transform" method="post" enctype="multipart/form-data">
                    <input type="file" name="data_file" />
                    <input type="submit" />
                </form>
            </body>
        </html>
    """

@app.route('/transform', methods=["POST"])
def transform_view():
    f = request.files['data_file']
    if not f:
        return "No file"

    stream = io.StringIO(f.stream.read().decode("UTF8"), newline=None)
    csv_input = csv.reader(stream)
    #print("file contents: ", file_contents)
    #print(type(file_contents))
    print(csv_input)
    for row in csv_input:
        print(row)

    stream.seek(0)
    result = transform(stream.read())

    response = make_response(result)
    response.headers["Content-Disposition"] = "attachment; filename=result.csv"
    return response

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5001, debug=True)
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,我不能告诉你我多么感激你的努力.有效.你不仅解决了我的问题,还帮助我正确理解了代码的每一行.你太棒了. (4认同)
  • 是的,谢谢你的详细回复.在网上找不到合适的回复并不容易.你做到了 ;) (2认同)

Eid*_*o95 6

重要说明:此答案仅与SpooledTemporaryFile可用的平台相关。

进一步iLuveTux answer,您可以read()通过替换以下基于字符串的流创建来保存冗余调用:

stream = io.StringIO(f.stream.read().decode("UTF8"), newline=None)
Run Code Online (Sandbox Code Playgroud)

和:

stream = io.TextIOWrapper(f.stream._file, "UTF8", newline=None)
Run Code Online (Sandbox Code Playgroud)

例子:

stream = io.TextIOWrapper(f.stream._file, "UTF8", newline=None)
csv_input = csv.reader(stream)
print(csv_input)
for row in csv_input:
    print(row)
Run Code Online (Sandbox Code Playgroud)

更多信息:

表单数据解析器的 Werkzeug 默认流是SpooledTemporaryFile(从1.0.1 开始),您可以从中获取使用其_file成员的底层缓冲区。