by shigemk2

当面は技術的なことしか書かない

Pythonのマルチバイト文字列出力のちょっとしたメモ

Emacsのshell-commandで以下のようなPythonワンライナーを実行するとUnicodeEncodeErrorが発生した。

(shell-command-to-string "/usr/local/bin/python2.7 -c \"import sys; sys.stdout.write(u'テスト')\"")
"Traceback (most recent call last):
  File \"<string>\", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-8: ordinal not in range(128)
"

(shell-command-to-string "/usr/local/bin/python3.7 -c \"import sys; sys.stdout.write(u'テスト')\"")
"テスト"

今回shell-command-to-stringを使ったけどshell-commandでもcall-process-shell-commandでも結果はいっしょだった。

でも、端末で同じコマンドを実行してもエラーは起きない(文字化けするけど)。

$ /usr/local/bin/python2.7 -c "import sys; sys.stdout.write(u'テスト')"
ãã¹ã
$ /usr/local/bin/python3.7 -c "import sys; sys.stdout.write(u'テスト')"
テスト

いろいろ調べていたら以下のような記載があった(公式ではない)

Python determines the encoding of stdout and stderr based on the value of the LC_CTYPE variable, but only if the stdout is a tty. So if I just output to the terminal, LC_CTYPE (or LC_ALL) define the encoding. However, when the output is piped to a file or to a different process, the encoding is not defined, and defaults to 7-bit ASCII.

はい。 Python2.7での標準出力の文字コードは sys.stdout.encoding で設定されており、基本はLC_CTYPE/LC_ALL/LANGなどの設定を見てsys.stdout.encodingの値が設定されているのだが、ttyじゃなくてパイプ/リダイレクトなど別プロセスを経由して結果を出力しようとした場合、文字コードは何も設定されない(3.7ではこの問題は解消されているようだが)

Encoding of Python stdout - Exterior Memory What a Character! | QED and NOM

試しに以下のように出力結果をリダイレクトして別ファイルに出力すると、結果が違う。

$ /usr/local/bin/python2.7 -c "import sys; print(sys.stdout.encoding)"
UTF-8
$ /usr/local/bin/python3.7 -c "import sys; print(sys.stdout.encoding)"
UTF-8

$ /usr/local/bin/python2.7 -c "import sys; print(sys.stdout.encoding)" > test.out; cat test.out
None
$ /usr/local/bin/python3.7 -c "import sys; print(sys.stdout.encoding)" > test.out; cat test.out
UTF-8

shell-command系関数を実行してシェルスクリプトを実行したときもttyじゃないから、sys.stdout.encodingがNoneになり、よってUnicodeEncodeErrorとなる。

なので、Python2.7での対策は、事前に PYTHONIOENCODING でstdin/stdout/stderrのエンコーディングを強制すること。

$ export PYTHONIOENCODING=UTF-8; /usr/local/bin/python2.7 -c "import sys; print(sys.stdout.encoding)" > test.out; cat test.out
UTF-8

旅をしすぎてタイトルをつけるのがめんどくさなった。

awscli 1.16.80

今夏にはこんなかんじ

  • api-change:transcribe: Update transcribe command to latest version
  • api-change:comprehend: Update comprehend command to latest version
  • api-change:medialive: Update medialive command to latest version
  • api-change:firehose: Update firehose command to latest version
  • api-change:cognito-idp: Update cognito-idp command to latest version

Release 1.16.80 · aws/aws-cli · GitHub

memo Athena create tableまわり

読み方が安定しないSerDe

マネコンをポチポチしてテーブルを作る方法ではOpenSerDeはつくられないし、CSVファイル読み込みだとファイルの中身がダブルクオート囲みだったらデータの出力にダブルクオートが含まれる。 docs.aws.amazon.com

あと、ヘッダー行もデフォルトだと入るので、skip.header.line.countのオプションとかも入れる。 dev.classmethod.jp

awscli 1.16.78

そろそろだけど年末は休業したい

  • api-change:elasticbeanstalk: Update elasticbeanstalk command to latest version
  • api-change:apigatewaymanagementapi: Update apigatewaymanagementapi command to latest version
  • api-change:ec2: Update ec2 command to latest version
  • api-change:globalaccelerator: Update globalaccelerator command to latest version
  • api-change:apigatewayv2: Update apigatewayv2 command to latest version

Release 1.16.78 · aws/aws-cli · GitHub

memo greple msdoc

  • Ubuntu 18.10
  • Perl v5.26.2
sudo cpan install App::Greple::perl 
# 入っていないやつちょこちょこいれてく
sudo cpan install Graphics::ColorNames:WWW 
sudo cpan install Getopt::EX::Loader
sudo apt-get install cpanminus
sudo cpanm App::Greple::msdoc
greple -Mmsdoc "テスト" *.docx 

GitHub - kaz-utashiro/greple: greple: extensible grep with lexical expression and region handling

Kimiya Kitaniのブログ纏めサイト: greple + App::Greple::msdoc で Microsoft Office ドキュメントをコマンドラインから検索、テキスト抽出(出力)する!