我想知道是否有人对python和gae有更好的理解可以帮助我解决这个问题。我正在将一个csv文件从表单上传到gae数据存储区。
class CSVImport(webapp.RequestHandler):
def post(self):
csv_file = self.request.get('csv_import')
fileReader = csv.reader(csv_file)
for row in fileReader:
self.response.out.write(row)
我遇到了其他人在这里提到的问题 - http://groups.google.com/group/google-appengine/browse_thread/thread/bb2d0b1a80ca7ac2/861c8241308b9717
也就是说,csv.reader迭代每个字符而不是行。一位谷歌工程师留下了这个解释:
调用self.request.get('csv')返回一个String。当你迭代一个 字符串,你迭代字符,而不是行。你可以看到 区别在于:
class ProcessUpload(webapp.RequestHandler):
def post(self):
self.response.out.write(self.request.get('csv'))
file = open(os.path.join(os.path.dirname(__file__), 'sample.csv'))
self.response.out.write(file)
# Iterating over a file
fileReader = csv.reader(file)
for row in fileReader:
self.response.out.write(row)
# Iterating over a string
fileReader = csv.reader(self.request.get('csv'))
for row in fileReader:
self.response.out.write(row)
我真的不遵循解释,并且没有成功实施。任何人都可以提供更明确的解释和建议的解决方案吗?
谢谢, 八月
答案 0 :(得分:13)
简短回答,试试这个:
fileReader = csv.reader(csv_file.split("\n"))
答案很长,请考虑以下事项:
for thing in stuff:
print thing.strip().split(",")
如果stuff是文件指针,则每个东西都是一行。如果stuff是一个列表,那么每个东西都是一个项目。如果stuff是一个字符串,那么每个东西都是一个字符。
迭代csv.reader返回的对象将给你类似于迭代传入的对象的行为,只对每个CSV解析的项目。如果您遍历一个字符串,您将获得每个字符的CSV解析版本。
答案 1 :(得分:8)
我想不出比你提到的谷歌工程师所说的更明确的解释。所以让我们稍微分解一下。
Python csv
模块对类似文件的对象进行操作,即文件或行为类似于Python文件的对象。因此,csv.reader()希望得到一个文件对象,因为它只是必需的参数。
webapp.RequestHandler
请求对象提供对表单中发布的HTTP参数的访问。在HTTP中,参数作为键值对发布,例如csv=record_one,record_two
。当您调用self.request.get('csv')
时,这将返回与密钥csv关联的值作为Python字符串。 Python字符串不是类文件对象。显然,当csv
模块不理解对象并简单地迭代它时,它就会回落(在Python中,字符串可以按字符迭代,例如,for c in 'Test String': print c
将打印字符串中的每个字符在另一条线上。)
幸运的是,Python提供了一个StringIO类,它允许将字符串视为类文件对象。所以(假设GAE支持StringIO,并且没有理由不应该这样做)你应该能够做到这一点:
class ProcessUpload(webapp.RequestHandler):
def post(self):
self.response.out.write(self.request.get('csv'))
# Iterating over a string as a file
stringReader = csv.reader(StringIO.StringIO(self.request.get('csv')))
for row in stringReader:
self.response.out.write(row)
哪个会按预期工作。
编辑我假设您使用类似<textarea/>
的内容来收集csv文件。如果您正在上传附件,可能需要进行不同的处理(我不熟悉Python GAE或它如何处理附件)。
答案 2 :(得分:0)
您需要致电csv_file = self.request.POST.get("csv_import")
而不 csv_file = self.request.get("csv_import")
。
第二个只是给你一个你在原帖中提到的字符串。但是,通过self.request.POST.get
访问会为您提供cgi.FieldStorage个对象。
这意味着您可以调用csv_file.filename
来获取对象的文件名,并调用csv_file.type
来获取mimetype。
此外,如果您访问csv_file.file
,它是一个StringO对象(来自StringIO module的只读对象),而不仅仅是一个字符串。正如his answer中提到的ig0774,StringIO模块允许您将字符串视为文件。
因此,您的代码可以简单地为:
class CSVImport(webapp.RequestHandler):
def post(self):
csv_file = self.request.POST.get('csv_import')
fileReader = csv.reader(csv_file.file)
for row in fileReader:
# row is now a list containing all the column data in that row
self.response.out.write(row)