无法解析使用 Flask 上传的 .csv 文件 [英] Not able to parse a .csv file uploaded using Flask
问题描述
我正在尝试上传 CSV 文件,对其进行处理以生成结果,然后写回(下载)包含结果的新 CSV 文件.我对 Flask 非常陌生,我无法获得正确的" csv.reader
对象来进行迭代和处理.这是到目前为止的代码,
I am trying to upload a CSV file, work on it to produce results, and write back (download) a new CSV file containing the result.
I am very new to Flask and I am not able to get a "proper" csv.reader
object to iterate and work upon.
Here is the code so far,
__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)
终端输出为
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']
而我读取的文件是
当我迭代 csv.reader 对象时没有得到代表 2 行的 2 个列表,我做错了什么?
What am I doing wrong to not get 2 lists representing 2 rows when I iterate the csv.reader object?
推荐答案
好的,所以您的脚本存在一个主要问题,csv.reader
如前所述 here 需要一个文件对象或至少一个支持迭代器协议的对象.您正在传递一个 str
,它确实实现了迭代器协议,但它不是遍历行,而是遍历字符.这就是为什么你有你所做的输出.
OK, so there is one major problem with your script, csv.reader
as noted here expects a file object or at least an object which supports the iterator protocol. You are passing a str
which does implement the iterator protocol, but instead of iterating through the lines, it iterates through the characters. This is why you have the output you do.
首先,它给出了一个单一字符 1
,csv.reader
将其视为具有一个字段的一行.之后 str
给出了另一个单个字符 ,
,csv.reader
将其视为具有两个空字段的行(因为逗号是字段分隔符).在整个 str
中一直如此,直到用完为止.
First, it gives a singe character 1
which the csv.reader
sees as a line with one field. After that the str
gives another single character ,
which the csv.reader
sees as a line with two empty fields (since the comma is the field seperator). It goes on like that throughout the str
until it's exhausted.
解决方案(或至少一种解决方案)是将 str
转换为类似文件的对象.我尝试使用 flask.request.files["name"]
提供的流,但这不会遍历行.接下来,我尝试使用 cStringIO.StringIO
并且似乎有类似的问题.我结束了这个问题它在通用换行符模式下建议了一个 io.StringIO
对象,该对象有效.我最终得到了以下工作代码(也许它会更好):
The solution (or at least one solution) is to turn the str
into a file-like object. I tried using the stream provided by flask.request.files["name"]
, but that doesn't iterate through the lines. Next, I tried using a cStringIO.StringIO
and that seemed to have a similar issue. I ended up at this question which suggested an io.StringIO
object in universal newlines mode which worked. I ended up with the following working code (perhaps it could be better):
__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)
这篇关于无法解析使用 Flask 上传的 .csv 文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!