如何使用csv.DictReader

时间:2019-08-15 15:59:14

标签: python python-3.x character-encoding

我为Flask应用程序使用以下python 3代码。对于应用程序(网站),您只需上传一个TXT或TSV文件(包含作者信息),该文件就会读入内存(因为它很小,并且该应用程序将被部署到一个只读文件系统中),然后该应用程序将进行格式化并以特定方式显示结果。

我遇到的问题是,当人们上传带有特殊字符的文件(例如,作者名字中的重音符号)时,出现错误

  File "/Users/cdastmalchi/Desktop/author_script/main.py", line 81, in process_file
    contents = csv.DictReader(file.read().decode('utf-8').splitlines(), delimiter='\t')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x96 in position 201: invalid start byte

带有特殊字符的示例行:

Department of Pathology, Lariboisière Hospital, APHP and Paris Diderot University, Sorbonne Paris

烧瓶代码:

@app.route('/process_file', methods=['POST'])
def process_file():
    # Run checks on the file
    if 'file' not in flask.request.files or not flask.request.files['file'].filename:
        return flask.jsonify({'result':'False', 'message':'no files selected'})
        return flask.redirect(url_for('home'))
    file = flask.request.files['file']
    filename = secure_filename(file.filename)
    if not allowed_file(file.filename):
        return flask.jsonify({'result':'False', 'message':'Must be TXT file!'})
        return flask.redirect(url_for('home'))

    # Stream file and check that places exist
    contents = csv.DictReader(file.read().decode('utf-8').splitlines(), delimiter='\t')
    check_places, json_data = places_exist(contents)

    if check_places is False:
        return flask.jsonify({'result':'False', 'message':'There is an affiliation missing from your Place list. Please re-try.'})
        return flask.redirect(url_for('home'))

    flask.session['filename'] = json_data
    return flask.jsonify({'result':'True'})

更新

当我执行uchardet {file.tsv}(其中file.tsv是带有特殊字符的测试文件)时,输出为ISO-8859-9

更新2:

这是我尝试在带有特殊字符的测试文件中使用csv.Sniffer()的尝试。但是我不太确定如何转换此代码以使用内存中的文件。

import csv

sniff_range = 4096
delimiters = ';\t,'

infile_name = 'unicode.txt'

sniffer = csv.Sniffer()

with open(infile_name, 'r') as infile:
    # Determine dialect
    dialect = sniffer.sniff(
        infile.read(sniff_range), delimiters=delimiters
    )
    infile.seek(0)

    # Sniff for header
    has_header = sniffer.has_header(infile.read(sniff_range))
    infile.seek(0)

    reader = csv.reader(infile, dialect)

    for line in reader:
        print(line)

输出:

['Department of Pathology', 'Lariboisière Hospital', 'APHP and Paris Diderot University', 'Sorbonne Paris']

问题::如何修改csv.DictReader代码以处理这些特殊字符(请注意,我只能将文件读入内存)?

更新3:

我的问题与涉嫌的欺骗不同,因为我试图弄清存储在内存中的文件的编码,这使事情变得更加棘手。我正在尝试在我的process_file Flask路由中实现以下方法以确定编码,其中file在这种情况下是Flask文件存储对象(file = flask.request.files['file'])。但是,当我尝试打印contents中的行时,我什么也没得到。

file = flask.request.files['file']
result = chardet.detect(file.read())
charenc = result['encoding']

contents = csv.DictReader(file.read().decode(charenc).splitlines(), delimiter='\t')

1 个答案:

答案 0 :(得分:1)

此版本的代码已成功为我解码并打印了文件。

  @app.route('/process_file', methods=['POST'])
  def process_file():
      # Run checks on the file
      file = flask.request.files['file']
      result = chardet.detect(file.read())
      charenc = result['encoding']

      file.seek(0)
      # Stream file and check that places exist
      reader = csv.DictReader(file.read().decode(charenc).splitlines())
      for row in reader:
          print(row)

      return flask.jsonify({'result': charenc})