「Print LF with Python to Windows stdout」へのインチキ解は MSYS に乗せて

一つ前で「Unix 的」なネタを書いた「ついで」というかなんというか。ちょっと思い出したもんで。

「Windows でも CR LF でなく LF で」に関する「積年のストレス」なんてのは、誰しも経験してるはず。このことに最も敏感に反応するのは多分 emacs ユーザ。特に .emacs にこんなん:

1 ;;
2 (setq coding-system-for-read 'utf-8-unix)
3 (setq coding-system-for-write 'utf-8-unix)

書いてる人はなおさら。この設定だと CR が「制御文字」として見えちゃう。emacs ユーザでなくても、(最近はほとんどないけれど)古典的で Unix 生まれの OSS が「CR LF だと処理を誤る」なんてのもあったわけで、一度もストレスを感じたことがないエンジニアの方が稀なんでわ。

で Python でのソレ。「stdout」(or stdin, stderr)でない場合は、別に難しくはなくて、2.7+ 前提なら io モジュールに頼るのが楽かと思う:

1 # -*- coding: utf-8 -*-
2 from __future__ import unicode_literals
3 
4 import io
5 with io.open("out.txt", mode="wb") as fo:
6     fo.write("aaa\n".encode("utf-8"))

C/C++ での考え方とほぼ同じく、「バイナリモードで」読み書きすればいいだけのこと。

ところがこれが「stdout, stdin, stderr」になると途端にダークサイドに突入する。「Python 2 まで」だけを扱っていれば良かった頃はもっと話はシンプルだったんだけれども、どちらでも動作するように、と考えると凄まじく「面倒」。これの解は StackOverflow にそのものズバリが書いてあるのでそっち見れ。

なんだけれど、こんなん「日常タスクとしての日々のゴミスクリプト」ごときのためにやるようなことではなくて、「オレだけ良ければいいのだ」のつもりなら、まさに「考えたくない」わけな。だって、「そういったゴミスクリプト」は、少なくともワタシにとっては「毎日書く」類のもんなんだから。

一つ前の話にも通ずるんだけれど、これへの「日々のインチキな立ち向かい方」は、当然ワタシは何年もずっと「知ってるし使ってる」わけよ。だけど、だからこそ「皆に教えねば!」とは思わない、あまりに日常過ぎて。だけれども、こうやって伝える機会を作らない限り、「知らない人がずっと知らないまま」という類の話かと思う。ので、一度は書いておこうかと。

この解は、見出しにした通り「MSYS に頼る」というもの。MSYS、といっているけれど、持っているのが MSYS2 だろうが cygwin だろうがどっちでも(たぶん)いい。どれでもたぶん出来る。

コード引用しにくいので、言葉だけで説明する。これだけ:

  1. Python スクリプトの出力を sed にパイプする
  2. sed のスクリプトは「s/CRで終わる//」
  3. 「CR」の入力は、bash であれば ctrl-v ctrl-m、emacs であれば ctrl-q ctrl-m

MSYS は標準入出力を「がんばって DOS モードに読み替える」ことを一切しないので、sed で CR を取り除くことに成功出来る限り、その出力をファイルにリダイレクトすれば目的の「Windows なのに LF エンディング」なテキストファイルを作れる。

この解が「唯一のもの・最適なもの」ということでないのは言うまでもない。実際「せっかく入力した制御文字」も、運搬で失ってしまう可能性があるので、「ええもん」ではない。事実、実際のコマンドラインをこの WordPress 記事に引用できないことからもわかるだろう。けど「最手っ取り早い」ではある、「制御文字を入力出来るのであれば」。

それと、この解が正当化出来るのは「オレさまさえ良ければ良いのだ」の場合に限る。多くの人に使ってもらいたいようなものを作るつもりならば、諦めて「ちゃんと Python 内で完結したアプローチで解決」させなはれ。ゆえに「ワタシから聞いたとは言わないで」。


ところで蛇足なんだけれど、「CR LF なんて非合理的だ! だから Windows はクソなんだ」てことではないからな。ワタシも若い頃そう思ってたけれど、実際はそうじゃない。いっけんすると「Unix 流儀の方がシンプル」に見えるけれど、これは見方が一面的過ぎ。

「ディスプレイに対する指示をコード化する」という意味では、「復帰して、行送りする」というふうに愚直に素直にマッピングしたのが Windows 流儀。しかもこれ、「Windows だけの流儀」でもないので注意。

ぼくらエンジニアが、それでもなお「Windows でのこれ」を嫌悪するのは、実際は「融通がきかない」というただ一点についてだけ。「なんでそんなに是が非でも郷に従うのだ、従いたくない場合も簡単に出来れっ!」という怒り、なわけだ。(要するにシンプルに制御させてくれ、てことな。だって「CR LF にする」ことも「LF にする」こともどっちも「ニーズ」なんだから、容易に行き来できないと困る。)