Загрузить и проанализировать CSV-файл с помощью Google App Engine - PullRequest
7 голосов
/ 04 июня 2010

Мне интересно, может ли кто-нибудь с лучшим пониманием 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') возвращает строку. Когда вы перебираете Строка, вы перебираете символы, а не строки. Вы можете увидеть разница здесь:

 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) 

Я действительно не следую объяснению, и мне не удалось его реализовать. Кто-нибудь может дать более четкое объяснение этого и предложенного исправления?

Спасибо, Август

Ответы [ 3 ]

13 голосов
/ 04 июня 2010

Краткий ответ, попробуйте это:

fileReader = csv.reader(csv_file.split("\n"))

Длинный ответ, учтите следующее:

for thing in stuff:
  print thing.strip().split(",")

Если вещи - это указатель на файл, каждая вещь - это строка. Если материал - это список, каждая вещь - это элемент. Если материал - это строка, каждая вещь - это символ.

Итерирование по объекту, возвращенному csv.reader, даст вам поведение, похожее на итерирование по переданному объекту, только с каждым элементом, проанализированным CSV. Если вы перебираете строку, вы получите CSV-версию каждого символа.

8 голосов
/ 04 июня 2010

Я не могу придумать более четкого объяснения, чем то, что сказал инженер Google, которого вы упомянули.Итак, давайте разберемся с этим немного.

Модуль 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) 

, который будет работать, как вы ожидаете.* Edit Я предполагаю, что вы используете что-то вроде <textarea/> для сбора файла CSV.Если вы загружаете вложение, может потребоваться другая обработка (я не очень знаком с Python GAE или с тем, как он обрабатывает вложения).

0 голосов
/ 01 августа 2016

Вам нужно позвонить 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 ), а не просто строка.Как 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...