haya14busa

haya14busa’s memo

zsh5.0.2に変えたら日本語打てなくなった問題と解決法

なんか勘違いしてたので書き直しました 2013/07/08。(記事投稿の翌日)

日本語入力できなかった

MacデフォルトのzshからHomebrewで最新のzsh(5.0.2)にしたらめっちゃ便利だったメモ « haya14busaで便利だーーーーと思ったのもつかの間、まさかの日本語入力すると多分ascii?コードに変換されちゃって、echoとかで実行させると普通の日本語に戻るって問題になった。LANG=ja_JP.UTF-8だし、setopt print_eight_bitは記述してたので詰んだかとおもい、やむなくバージョン戻そうかなーとおもったら解決法見つけました。

.zshrc.inputrc

set kanji-code utf-8 set convert-meta off #必須 set meta-flag on #必須 set output-meta on #必須 set input-meta on set enable-keypad on

Mac OSX x zsh で日本語表示 & 入力

set convert-meta offが解決策です。これがデフォルトでonっぽいのが原因でした。

いろいろ間違ってました。まず記述するファイルは.zshrcでなく.inputrcであるということ。これは調べると.zshrcに記述している例もたまに見かけるのですが、おそらく読み込んでないと思います。そもそもがこれらのコマンドは.inputrcに記述するもので、これはreadlineが読みにくるファイルなようです。そしてzshはreadlineではなくzleという独自の機能で履歴機能などを実装してるからです。

Note that unlike bash’s line editor, readline, which is an entirely separate library, zle is an integral part of the shell.

A User’s Guide to the Z-Shell

実際にon/off変えてみましたが(僕が見た限りでは)変化ありませんでした。

ここで怪我の功名で.inputrcがreadlineをある程度制御するファイルだと知れたことは幸いでした。なんてったってPythonで日本語入力できなかった問題が部分的には解決したわけですから。これはまた別の記事で。

これで心置きなく使え……る?ほんとに?

補完で表示される日本語ファイルはちゃんと”日本語.txt”と表示されるのに、lsコマンドでは”?????????.txt”に化けます。これは以前からの問題で、むしろ補完時はちゃんと表示される分より改善したんですが、正直ファイル名に日本語使うこと滅多に無いんで妥協してます。多分解決策あるんだろうけど………それよりもPythonのインタプリタで日本語使いたい…はぁ

lsで”?????????.txt”に化けるのはls -vのように-vオプションをつけると表示できました。

実際の解決法

実際の解決法………それは………versionを下げる!!!

はい、正直いい解決法とはいえません。でもしょうがない。そこまで思い入れもないし。ということでHomebrewで古いバージョンをインストールする方法です。

Mac – homebrewでバージョンを指定してインストールする – Qiita [キータ]

まずはバージョンを確認

% brew versions zsh
5.0.2    git checkout 4392eba /usr/local/Library/Formula/zsh.rb
5.0.1    git checkout 9d0b1be /usr/local/Library/Formula/zsh.rb
5.0.0    git checkout 9928fbb /usr/local/Library/Formula/zsh.rb
4.3.17   git checkout 8022bf4 /usr/local/Library/Formula/zsh.rb
4.3.16   git checkout 94841e1 /usr/local/Library/Formula/zsh.rb
4.3.15   git checkout 0c7ed4d /usr/local/Library/Formula/zsh.rb
4.3.12   git checkout d8c1bd1 /usr/local/Library/Formula/zsh.rb
4.3.11   git checkout 0476235 /usr/local/Library/Formula/zsh.rb
4.3.10   git checkout d0efd9e /usr/local/Library/Formula/zsh.rb

ディレクトリ移動して先ほどの確認で出てきた該当バージョンのgitコマンドをコピペ。ここでは4.13.15

% cd /usr/local/Library/Formula
% git checkout 0c7ed4d /usr/local/Library/Formula/zsh.rb

一応バージョンが変わってるか確認。5.0.2とかはbrew unlinkしただけなのでファイル残ってるみたいな記述ありますが無視で。

% brew info zsh                                                 (git)-[master]
zsh: stable 4.3.15

http://www.zsh.org/

/usr/local/Cellar/zsh/4.3.15 (932 files, 8.3M) *
  Built from source
/usr/local/Cellar/zsh/5.0.0 (957 files, 8.5M)
  Built from source with: --disable-etcdir
/usr/local/Cellar/zsh/5.0.2 (1053 files, 8.5M)
  Built from source
From: https://github.com/mxcl/homebrew/commits/master/Library/Formula/zsh.rb
==> Dependencies
Optional: gdbm
==> Options
--with-gdbm
    Build with gdbm support
==> Caveats
In order to use this build of zsh as your login shell,
it must be added to /etc/shells.

最後に現在Homebrewでzshがインストールされている場合は、brew rm zsh orbrew unlink zshしてからインストール

% brew install zsh

一応シェル扱ってるので、アンインストールする前にbashにログインして作業するとかMacデフォルトのzshにログインするとかしたほうがいいと思います。(全然別の件ですが一度シェルのPATH設定とか間違えて痛い目見ました)

バージョンに関しては僕が調べた限り、変な変換をかませず日本語入力できる最新のバージョンが4.3.15でした。4.3.16はエラー吐いて、4.3.17から挙動が変わります。Macデフォルトの/bin/zshのバージョンは4.13.11なのでHomebrewに移行する価値はあると思います。zsh-completionsをHomebrewから入れてるのなら尚更ですね。

なお、バージョンによってDependenciesなどが変わったりして、使用モジュール?が古いから変えるようにみたいなWarningでたりしますが、現状普通に動くと思います。

晴れて解決?

ただバージョン5.0.2などでもシェルのプロンプトで日本語がかってに変換されてしまうだけで、日本語の使用自体はできますし、vimなどでは普通に入力できるところを見ると、最新バージョンでも使える解決策があるんじゃないかなーとおもいます。ただ僕のぐぐり力では見つかりませんでした。それどころか自分の環境だけ問題おこってるという可能性すらありますよね。そう考えると、根本的な原因を知っときたい…

解決:Mac OSXのPythonのインタプリタで日本語入力する方法

環境

  • Mac OSX 10.8.4
  • Python 2.7.5 (Homebrewでインストール)
  • Python 3.3.2でも確認
  • readline 6.2.4(Homebrew)

Mac OSXのPythonのインタラクティブシェルorインタプリタで日本語が入力出来なくてつらい « haya14busa

やっと解決しました。まさかzsh調べてる過程でPythonの問題を解決できるとは思わなかった。

解決法

やっぱりreadline / GNU readlineの問題でした。readlineは~/.inputrcを読み込むようで、そこに下記の記述でPythonのインタプリタで(一応)日本語が打てるようになります。

~/.inputrc

kanji-code utf-8

# Enable 8bit input
set meta-flag on
set input-meta on

# Turns off 8th bit stripping
set convert-meta off

# Keep the 8th bit for display
set output-meta on

set enable-keypad on

いまいち.inputrcの再読み込みのやり方わからなかったんで、シェルごと再起動させて調べてました。

readlineの環境としてはHomebrewでインストールしたreadline6.2.4。PythonのDependenciesに含まれてるので、普通にbrew install pythonしてれば入ってますeasy_install readlineやpip install readlineはしてもしなくても変わりませんでした。特に後者はディレクトリの配置が優先されないのかそもそも機能してるか怪しいです。readlineをpipのみで入れるとimportでエラー吐くので。

とにかく、~/.inputrcに上記の記述でひとまず日本語を打つときに「ガッガッ」と警告音ならされて文字が消えることなく、入力できるはずです。

バグ挙動

訳注: IDLE をはじめ、ほとんどの Python 2 用のインタラクティブシェルは、非ASCII 文字を含む Unicode リテラルを利用することができません。このサンプルを実行するには、インタプリタ内蔵のインタラクティブシェルを利用する必要があります。 この問題は Python 3 では解決されています。

3. 形式ばらない Python の紹介 — Python 2.7ja1 documentation

そもそも公式ドキュメントで書いてある通り、インタプリタでの日本語の使用はあまりできないっぽいです。今回解決した結果も例に漏れずバクがあります。

まず最初に書いたURL -> Mac OSXのPythonのインタラクティブシェルorインタプリタで日本語が入力出来なくてつらい « haya14busa の記述と同様Pythonインタプリタで使用される文字エンコーディングをすべて’utf-8′に変えます。

~/.zshrc

export PYTHONSTARTUP=~/.pythonstartup
export PYTHONIOENCODING='utf-8'

~/.pythonstartup

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import codecs

sys.stdout = codecs.getwriter('utf_8')(sys.stdout)
sys.stdin = codecs.getreader('utf_8')(sys.stdin)

エンコーディングを変えた環境で開発するのは配布の際などに不具合をきたす可能性があがってよくないですが、日本語扱うためにはある程度しかたないです。そもそもインタプリタってちょっと気軽に確認したいってときに使うことが多いと思うので。また普通にスクリプトを実行する際は上記の記述はまったく関係ないはずなので問題ないと思います。

で…実行すると

% python
Python 2.7.5 (default, Jul  8 2013, 03:25:24) 
[GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.28)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 'こんにちは'
>>> type(a)
<type 'str'>
>>> len(a)
15
>>> print a
こんにちは
>>> b = u'こんにちは'
>>> type(b)
<type 'unicode'>
>>> len(b)
15
>>> print b
こんにちは

aに関してはいいですよ………問題はbです。len(b)が15ってなんだよ!ぉこだよ!?printで文字化けしてんじゃねーよ!!!

これじゃあ日本語入力できても結局確認にすら使えないですよね。そこでちょっと強引な解決法として

>>> c = unicode(a,'utf-8')
>>> type(c)
<type 'unicode'>
>>> len(c)
5
>>> print c
こんにちは
>>> c[1:3]
u'\u3093\u306b'
>>> print c[1:3]
んに

これだと文字列のスライスもできてますし、ちょっと日本語関係のコードを確認するときは一旦str型で入力したものをunicode(text,’utf-8′)すればちゃんと動くってことですね。これでひとまず解決!!!

ところでu”テキスト”とunicode(“テキスト”,’utf-8′)の違いってなんなんだろうか。

u_quote_and_unicode.py

# coding:utf-8
print u"てきすと" == unicode("てきすと",'utf-8') # True

シェルでなくスクリプトファイルで確認するとTrueだったので違いはないのかな?

ちなみにPython3のインタプリタで試した所、無駄なこと一切せず動きます。文字コードに関しては3に移行したいと思った。ついでに言うとPyrhon2.6から実装されたfrom future import unicode_literalsすると全部u”てきすと”の扱いになるので今回は逆効果です。

あとインタプリタ上で日本語入力ができてるように見えますけど、内部?では1文字の「あ」ではなくカーソル3つ分くらいの長さを持ってるので、カーソルを移動させたり、消去すると表示がバグります。いったん何文字か売ってカーソルを左に移動させてからもう一度右にするとわかりやすいです。……ということで日本語部分を書き直すなら文頭から全部書きなおすようにしたほうがいいですね。

最初に数文字打って………

Screen Shot 2013-07-08 at 9.08.49 AM カーソルを左右に移動させると……… Screen Shot 2013-07-08 at 9.09.36 AM

MacデフォルトのzshからHomebrewで最新のzsh(5.0.2)にしたらめっちゃ便利だったメモ

参考リンク

導入

シェル

% brew install --disable-etcdir zsh
% brew install zsh-completions
% sudo sh -c "echo '/usr/local/bin/zsh' >> /etc/shells"
% chsh -s /usr/local/bin/zsh
% echo 'fpath=(/usr/local/share/zsh-completions $fpath)' >> ~/.zshrc
% source ~/.zshrc
% rm -f ~/.zcompdump; compinit

すでにMacデフォルトのzsh使ってたのでtouch ~/.zshrcとかは省略。

バージョンがどうのこうのよりもそもそもzsh全然調べてないのが問題だった。zsh-completionsすごい。いままでbrewコマンドの引数とか補完できてなくて手打ちしてたけどめっちゃ出てくるようになった。完全に持て余してたらしい。bashからzshに変えた感動再び。.zshrcの記述とかももっと調べなきゃ。

追記

日本語の入力でつまずきました。

zsh5.0.2に変えたら日本語打てなくなった問題と解決法 « haya14busa

Mac OSXのPythonのインタラクティブシェルorインタプリタで日本語が入力出来なくてつらい

参考リンク

環境

  • Mac OSX 10.8.4
  • Python 2.7.5 (Homebrewでインストール)

MacのPythonインタプリタで日本語が入力出来なくてつらい。つらい

Snow Leopardだとeasy_install readlineで解決するって記事がもう嫌になるほど見つかるけど僕の環境では全く解決しません。

ただなんにせよreadlineの問題であることはわかりました。

単にreadlineといっても

  1. Mac標準のreadline
  2. Homebrewで入れるreadline
  3. easy_installで入れるreadline
  4. pipで入れるreadline

もう何がなんだか…。1と2はライセンスの関係で少し違うらしいこと、3と4は同じかと思いきやHomebrewのreadlineをアンインストールした状態で3のeasy_installでは上手くimportできるのに、4のpipではimportエラーが発生します。

Homebrewでのreadlineをアンインストールした状態で,pip install readlineした時のエラー

ImportError: dlopen(/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/readline.so, 2): Library not loaded: /usr/local/opt/readline/lib/libreadline.6.2.dylib
  Referenced from: /usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/readline.so
  Reason: image not found

readlineの問題だと考えるのはHomebrew、easy_install、pipのすべてでreadlineをアンインストールした場合、ちゃんと日本語が通ります。ただ勿論readlineが使えないので補完はおろか矢印キーさえ動きません。これはツライ。

1-4でいろんな組み合わせでreadlineをインストール&アンインストールしてもimportできた場合はすべて日本語通りません…

.zshrc

export PYTHONSTARTUP=~/.pythonstartup
export PYTHONIOENCODING='utf-8'

.pythonstartup

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import codecs

sys.stdout = codecs.getwriter('utf_8')(sys.stdout)
sys.stdin = codecs.getreader('utf_8')(sys.stdin)

上記の2つを設定して、Pythonシェルでのエンコーディングをすべてutf-8にしても解決せず。utf-8に変更する前はUS-ASCIIだったんでこれが問題かと思ったんだけど……

Python インタプリタ

import sys
>>> print sys.getfilesystemencoding()
utf-8
>>> print sys.stdin.encoding
utf-8
>>> print sys.stdout.encoding
utf-8
>>> print sys.stderr.encoding
utf-8
>>> print sys.getdefaultencoding()
utf-8

もちろんLANG=ja_JP.UTF-8状態にもしてるし、ターミナルではちゃんと日本語入力できるのに…

brew link readlineとかやったり、brewで入れたreadlineを使うように(?)Homebrew使わず自前でPython入れなおしてみたりいろいろとやってみた………が………だめ

% CPPFLAGS=-I/usr/local/Cellar/readline/6.2.4/include LDFLAGS=-L/usr/local/Cellar/readline/6.2.4/lib  ./configure --prefix=/usr/local/Cellar/python/2.7.5 --enable-ipv6 --datarootdir=/usr/local/Cellar/python/2.7.5/share --datadir=/usr/local/Cellar/python/2.7.5 --enable-framework --with-universal-archs=intel --enable-universalsdk=/

% make
% sudo make frameworkinstall

書きながら調べてたらここを見つけた。-> Pythonビルドメモ(2013/02/09版) – 日々の御伽噺

というか参考にしてたリンクの更新版的な記事だったのでやっぱ検索力足りてない…試してみようかな

追記

なんとか解決できました

解決:Mac OSXのPythonのインタプリタで日本語入力する方法 « haya14busa

PythonでTwitterのタイムラインをストリーミングで読み上げさせるfor Mac[tweepy]

作りま……パクりました

初心者ながらPythonでツイッターのタイムライン読み上げさせたら面白いなーと思って頑張ってました。最初は何も考えずpython-twitterで試行錯誤してたんだけど、tweepyはStreaming APIにも対応しててtweepy使った方が楽なことを発見。んでググってたらそのままターミナルにストリーミングでTL流すスクリプト見つけたので、そこにSayKotoeriコマンドをプラスしてちょっと変えただけのほぼ丸パクリです。頑張って自分で作ったのは別記事のリストを擬似ストリーミングで読み上げさせる方なので、ご了承ください。

リストバージョン -> PythonでツイッターのリストのTLを擬似ストリーミングで読み上げさせる[tweepy] « haya14busa

tweepyのインストール

pip install tweepyでおけ。記事執筆現在API1.1にも対応してます。pipならバージョンは2.0でgithubには2.1が上がってるっぽいです。でも現場2.0で良さそう。公式ドキュメントのバージョンが1.4で古かったりして大変なので、バージョンに気を付けてググったり、dir()コマンドとかソース読んで自分で見ていくとわかりやすいっぽいです。

読み上げコマンド

Saykotoeri & SayKana , or Saykotoeri2コマンドが必要です。リンク先からインストールしてください。デフォルトのsayコマンドでKyokoさんをインストールして使うのもいいけどKyokoさんは漢字全然読めないからお察し。英語を読ませる場合、sayコマンドの発音は凄いと思います。英語用リストではsayコマンド使ってます。

SayKotoeri2の方がいろいろコマンドのオプションがあって使いやすいんだけど、女性1、いわゆるゆっくり(れいむ)の声がSayKotoeriの方でしか使えなかったんでやむなくSayKotoeri使ってます。SayKotoeri2で同じ声使う方法知ってる方がいらしたら教えてほしい。

それとSayKotoeriは英語が全然読めないのでことえり辞書で教育するといいっぽいです。(例: 読み->ついったー, 単語:Twitter)
それ用の辞書入れたら良いのだろうけど無料でいいやつは現状ないかも。シェアウェアなら->NADのカタカナ英語辞書(シェア)

一応正規表現でツイートに埋め込まれてるURLを「URL」, RTを「Retweet」に置換などはしてますがもっと置換のパターン増やせばよりストレスなく聞き取れるかも。

コード

twAloud.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#
# Timelineをストリーミングで読み上げさせる
# 
# Author:   haya14busa
# URL:      http://haya14busa.com
# require:  SayKotoeri, Saykana or SayKotoeri2
# OS:       for Mac Only
# Link:     [twitterをターミナル上で楽しむ(python)](http://www.nari64.com/?p=200)

import tweepy
from tweepy import  Stream, TweepError
import logging
import urllib
from subprocess import call
import re
import sys, codecs

sys.stdout = codecs.getwriter('utf_8')(sys.stdout)
sys.stdin = codecs.getreader('utf_8')(sys.stdin)

def get_oauth():
    CONSUMER_KEY='**********'
    CONSUMER_SECRET='**********'
    ACCESS_TOKEN_KEY='**********'
    ACCESS_TOKEN_SECRET='**********'

    auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
    auth.set_access_token(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET)
    return auth

def str_replace(string):
    string = re.sub('&.+;', ' ', string)
    # remove URL
    string = re.sub('(https?|ftp)(:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+)', 'URL', string)
    # remove quote
    string = re.sub('"', ' ', string)
    string = re.sub("'", ' ', string)
    string = re.sub('\/', ' ', string)

    string = re.sub('RT', 'Retweet', string)
    return string

class CustomStreamListener(tweepy.StreamListener):

    def on_status(self, status):

        try:
            print u'---{name}/@{screen}---\n   {text}\nvia {src} {created}'.format(
                    name = status.author.name,
                    screen = status.author.screen_name,
                    text = status.text,
                    src = status.source,
                    created = status.created_at)
            read_text = str_replace(status.text.encode('utf-8'))
            call(['SayKotoeri -s "-s 120" "{text}" >/dev/null 2>&1'.format(text=read_text)], shell=True)

        except Exception, e:
            print >> sys.stderr, 'Encountered Exception:', e
            pass

    def on_error(self, status_code):
        print >> sys.stderr, 'Encountered error with status code:', status_code
        return True # Don't kill the stream

    def on_timeout(self):
        print >> sys.stderr, 'Timeout...'
        return True # Don't kill the stream


class UserStream(Stream):

    def user_stream(self, follow=None, track=None, async=False, locations=None):
        self.parameters = {"delimited": "length", }
        self.headers['Content-type'] = "application/x-www-form-urlencoded"

        if self.running:
            raise TweepError('Stream object already connected!')

        self.scheme = "https"
        self.host = 'userstream.twitter.com'
        self.url = '/2/user.json'

        if follow:
           self.parameters['follow'] = ','.join(map(str, follow))
        if track:
            self.parameters['track'] = ','.join(map(str, track))
        if locations and len(locations) > 0:
            assert len(locations) % 4 == 0
            self.parameters['locations'] = ','.join(['%.2f' % l for l in locations])

        self.body = urllib.urlencode(self.parameters)
        logging.debug("[ User Stream URL ]: %s://%s%s" % (self.scheme, self.host, self.url))
        logging.debug("[ Request Body ] :" + self.body)
        self._start(async)

def main():
    auth = get_oauth()
    stream = UserStream(auth, CustomStreamListener())
    stream.timeout = None
    stream.user_stream()

if __name__ == "__main__":
    main()

使い方

Twitter Developersに登録してCONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRETをそれぞれ取得してコードの該当位置に書き込んでください。PINコードで認証とかは気が向いたらまた考える。

読み上げコマンド含め好きなように編集して使ってください。デフォルトだと一般的なゆっくりの声です。もちろん読み上げなしにして授業中や会社でばれないようにツイッターするのもよし。

あとはターミナルでpython twaloud.py 終了はCtrl-Cで強制終了してください。

それとデフォルトのTerminal.appよりもiTerm2だとコマンドクリックでURL開けるのでタイムライン読むのに便利です。

参考リンク

ライブラリ

リストバージョン

コード

読み上げ関連