2010/11/26

pfff の formula 書いてみたけどうまくいかなかったの巻

これ良さげだなーと思ってインストールしようと思ったんだけど、どうせだしただインストールするんじゃなくて Homebrew の formula 書いてみようと思って試してみた。

既存の formula を参考に適当に書いた。たしかに書きやすいし楽だ。

require 'formula'
class Pfff  :optional
  depends_on 'libsvg-cairo' => :optional

  def install
    system "./configure", "--prefix=/usr/local/Cellar/pfff/0.13"
    system "make depend"
    system "make"
   
    bin.install "pfff"
    bin.install "sgrep"
    bin.install "spatch"
    bin.install "scheck"
    bin.install "stags"
    bin.install "codemap"
    bin.install "pfff_db_light"
  end
end

これでいいだろう、って思って

$ brew install pfff --HEAD

ってやるとエラーが出て make の段階で止まる。 ちなみに、普通に git clone して configure、make depend、make のコマンド叩いて実行するとエラー出ないでコンパイル完了する…。なんで?環境変数?

pcre も /opt/local/include/pcre.h 見てファイル無いよとか configure でエラー吐くしなんか微妙な感じなんだけど、scheck とか結構重宝しそう。今のところ使ってない変数の報告くらいしか見てないけど。

誰か TextMate の bundle 作ってくれるのを待ちたいと思います。

2010/11/18

pip で PyPI のパッケージ更新状況を確認する

いつの間にか yolk がお亡くなりになってて微妙に不便だったから、コピペででっちあげた。

パッケージの名前渡したらヴァージョンチェックしてくれるメソッド用意されてると思ったんだけど、無いくさいからいちいち検索してるのがちょっとアレ。

pip outdated

でもまぁ、いいと思います!

import pkg_resources
import xmlrpclib
import pip
import pip.download
from pip.log import logger
from pip.basecommand import Command
from pip.util import get_installed_distributions
from pip.commands.search import transform_hits, compare_versions, highest_version

class OutdatedCommand(Command):
    name = 'outdated'
    usage = '%prog'
    summary = 'check updated packages'
    
    def __init__(self):
        super(OutdatedCommand, self).__init__()
    
    def run(self, options, args):
        index_url = 'http://pypi.python.org/pypi'
        
        for dist in get_installed_distributions(local_only=True):
            pypi_hits = self.search(dist.key, index_url)
            hits = transform_hits(pypi_hits)
            print_results(hits)
    
    def search(self, query, index_url):
        pypi = xmlrpclib.ServerProxy(index_url, pip.download.xmlrpclib_transport)
        hits = pypi.search({'name': query})
        return hits


def print_results(hits):
    installed_packages = [p.project_name for p in pkg_resources.working_set]
    for hit in hits:
        name = hit['name']
        
        try:
            if name in installed_packages:
                dist = pkg_resources.get_distribution(name)
                try:
                    latest = highest_version(hit['versions'])
                    if dist.version < latest:
                        logger.notify('%s: %s => %s' % (name, dist.version, latest))
                finally:
                    pass
        except UnicodeEncodeError:
            pass


OutdatedCommand()

2010/11/17

SQLAlchemy で collate が utf8_bin なカラムだとユニコード文字列で取得出来ない

某システムで検索の仕様変えることになって(厳密にはいろいろ違うけど)、大文字小文字の区別付けるために検索対象のカラムの collate を utf8_general_ci から utf8_bin に変更した。

ALTER TABLE `hoge` MODIFY `col` VARCHAR(255) NOT NULL DEFAULT '' CHARACTER SET utf8 COLLATE utf8_bin

検索は PHP で書いてて、テストも問題無かったからデプロイしたんだけど、このテーブルを Python で書いたクローラも参照してたから、ちょっと問題が出た。

from sqlalchemy import *
from sqlalchemy.sql import select

engine = create_engine('mysql://localhost/sandbox', echo=False, encoding='utf-8', convert_unicode=True)
conn = engine.connect()
metadata = MetaData(bind=engine)
tbl1 = Table('table1', metadata, autoload=True)

for row in conn.execute(select([tbl1])):
    print row # Unicode文字列になっていない

ORM 使わないで書いてたやつなんだけど、取得した結果の文字カラムがユニコード文字列になってなくて、お馴染の UnicodeDecodeError でクローラが落ちる…。

そもそもの書き方が悪い、っていうのがあるんだけど、一旦それは置いといて(というかすぐ直した)原因は何なのかってのを調べてみる。

ローカルの環境は MySQL 5.1.51 + SQLAlchemy 0.6.1 で、上記のコードを試すと結果はユニコード文字列になってる。

あれ、ってことで本番環境確認すると MySQL 5.0.91 + SQLAlchemy 0.6.1…なんだけど、DB サーバは別にあってそっちは MySQL 5.1.51。 SQLAlchemy のバージョン上げれば解決、だと思ったんだけど、問題解決にはならず結果は同じ…。

あんまり検証してないけど、とりあえずこういうことらしい。SQLAlchemy がその辺うまいこと処理してくれるものだと思ってたんだけど、どうなんだろう…。

それにしても余裕が無い…。

2010/11/13

Maatkit の mk-kill で SELECT だけを殺す

どうもこんばんは。 MySQL さっぱりわからないクズです。

いまいちクエリ改善できなくて、ヘタに検索すると刺さっちゃったりするシステム作ってしまった訳なんですけど、大人の事情でサーバのメモリ増設とかすんなり出来なかったりしてどうしようかなって状態だったりするんですが、とりあえず刺さったクエリを自動で殺す方法探したら Maatkit に含まれる mk-kill 使うのが一番手頃みたいだし cron*1 に仕込んでおいた。

$ mk-kill -kill-query --busy-time 1m

これで実行されてから1分以上経過したクエリが自動で殺されます。よかったよかった…なんですが、ALTER TABLE とかパーティションの更新とかもこれだと対象にされちゃうので、SELECT のみに限定したい場合は

$ mk-kill -kill-query --match-info SELECT --busy-time 1m

--match-info でパターンを指定してやればいいみたい。 info ってのがぱっと見だとわかりずらいけど、show processlist の info の部分ってことみたい。

ぜんぜんわかんないことばかりで悲しいんだけど、Maatkit 便利だしいろいろ試したい。

余談だけど、パーティションって2日先まで作って更新してくのがいいよね?とりあえず問題は出てないしデメリットも思いつかないから、このままでいくけど。。

*1: --daemonize のオプション指定してみたけどちゃんと動かなかった。 pid 指定してみても駄目。何かに依存してるのかな。

2010/11/07

do

  • MacBook も Homebrew に移行。とりあえず coreutils と tmux と zsh だけ入れた
  • limera1n で iPhone 4 を Jailbreak
何にも書かなくなっちゃったし、とりあえずその日にやったことだけでも記録付けるようにしたい。