2016-07-29 1 views
0

を使用してのPython 3への移行、私はビルトイン<code>csv</code>今、各文字列の周りに<code>b'</code>接頭辞を持っているを使用して、我々が生成するいくつかのファイルを気づいている間... csvモジュール

を非Unicodeを書くここで生成する必要があるコードは、ですdogsのリストについては、.CSVは、export_fieldsによって定義されたいくつかのパラメータ(これは常にUnicodeデータを返す)によると:私はfile_content.getvalue()を返したら

file_content = StringIO() 
csv_writer = csv.writer(
    file_content, delimiter='\t', quotechar='"', quoting=csv.QUOTE_MINIMAL 
) 
csv_writer.writerow([ 
    header_name.encode('cp1252') for _v, header_name in export_fields 
]) 
# Write content 
for dog in dogs: 
    csv_writer.writerow([ 
     get_value(dog).encode('cp1252') for get_value, _header in export_fields 
    ]) 

問題がある、私が取得:

b'Does he bark?' b'Full  Name' b'Gender' 
b'Sometimes, yes' b'Woofy the dog' b'Male' 

代わりの(インデントはSO上で読めるように変更されました)

'Does he bark?' 'Full  Name' 'Gender' 
'Sometimes, yes' 'Woofy the dog' 'Male' 

私はcsvモジュール内の任意のencodingパラメータを見つけることができませんでした。私は、ファイル全体がcp1252でエンコードされるようにしたいので、エンコーディングが行の繰り返しか、ファイル自体のコンストラクションによって行われるかどうかは気にしません。

したがって、cp1252でエンコードされた文字列のみを含む適切な文字列を生成する方法を知っている人はいますか?

+0

あなたが最初の場所でエンコードされているのはなぜ?開いているファイルオブジェクトがそれを処理します。 –

+0

@MartijnPieters多分私の質問は不完全です:私はDjangoを介して文字列を返す: 'return HttpResponse(generate_csv_file())'。代わりにDjangoレベルでエンコーディングを処理する必要がありますか? –

+0

私の答えを見てください。あなたは間違ったレベルでこれに近づいています。タブやクオートチャルもエンコードする必要がありますが、これは 'csv'モジュールやコードを生成するコードではなく、I/Oレベルの仕事です。 –

答えて

1

モジュールはテキストを扱い、str()を使用して文字列ではないものを文字列に変換します。

bytesオブジェクトを渡さないでください。 str()で完全に文字列に変換するオブジェクトまたはタイプstrを渡します。つまり、は文字列をエンコードしないでください。

あなたがcp1252出力が必要な場合は、StringIO値をエンコード:

file_content.getvalue().encode('cp1252') 

StringIOなどのオブジェクトも、テキストのみを扱っています。いっそ

csvモジュールは、ファイルオブジェクトへの書き込みとあなたのための符号化を行うためにTextIOWrapper()BytesIO objectを使用します。

from io import BytesIO, TextIOWrapper 

file_content = BytesIO() 
wrapper = TextIOWrapper(file_content, encoding='cp1252', line_buffering=True) 
csv_writer = csv.writer(
    wrapper, delimiter='\t', quotechar='"', quoting=csv.QUOTE_MINIMAL) 

# write rows 

result = file_content.getvalue() 

いるので私はラッパー上のラインバッファリングを有効にしています行が書き込まれるたびにBytesIOインスタンスに自動的にフラッシュされます。今

file_content.getvalue()は、バイト文字列を生成します。

>>> from io import BytesIO, TextIOWrapper 
>>> import csv 
>>> file_content = BytesIO() 
>>> wrapper = TextIOWrapper(file_content, encoding='cp1252', line_buffering=True) 
>>> csv_writer = csv.writer(wrapper, delimiter='\t', quotechar='"', quoting=csv.QUOTE_MINIMAL) 
>>> csv_writer.writerow(['Does he bark?', 'Full  Name', 'Gender']) 
36 
>>> csv_writer.writerow(['Sometimes, yes', 'Woofy the dog', 'Male']) 
35 
>>> file_content.getvalue() 
b'Does he bark?\tFull  Name\tGender\r\nSometimes, yes\tWoofy the dog\tMale\r\n' 
+0

それは本当に(一度フラッシュされたが、あなたがコメントする時間がある前に編集した)本当にラッパーで動作するように見えます。テストで99%が合格と答えています:) –

+0

@MaximeLorant:私は今、ラインバッファリングを使用するように切り替えました。手動でフラッシュする必要はありません。申し訳ありません。 –

+0

実際にクリーナーに見えます!先端に感謝します。 –

関連する問題