web-dev-qa-db-ja.com

Python HDFSからストリームとしてファイルを読み取る

ここに私の問題があります:私は潜在的に巨大になる可能性があるHDFSのファイルを持っています(=メモリにすべてを入れるには十分ではありません)

私がやりたいのは、このファイルをメモリにキャッシュすることを避け、通常のファイルで行うように行ごとに処理することです:

for line in open("myfile", "r"):
    # do some processing

外部ライブラリを使用せずにこれを正しく実行する簡単な方法があるかどうかを確認しています。おそらく libpyhdfs または python-hdfs で動作させることができますが、可能であれば、特にこれらの両方からシステムに新しい依存関係とテストされていないライブラリを導入しないようにしたいです重くメンテナンスされていないようで、本番環境では使用しないでください。

Python subprocessモジュールを使用する標準の "hadoop"コマンドラインツールを使用してこれを行うことを考えていましたが、必要なことを実行できないようです。私の処理を行うコマンドラインツールはありません。すべての行に対してストリーミング方式でPython関数を実行したいと思います。

サブプロセスモジュールを使用して、パイプの正しいオペランドとしてPython関数を適用する方法はありますか?または、各行を簡単に処理できるように、ジェネレーターとしてファイルのように開きますか?

cat = subprocess.Popen(["hadoop", "fs", "-cat", "/path/to/myfile"], stdout=subprocess.PIPE)

外部ライブラリを使用せずに上記で説明したことを達成する別の方法がある場合、私もかなりオープンです。

助けてくれてありがとう!

24
Charles Menguy

xreadlines が必要で、ファイル全体をメモリにロードせずにファイルから行を読み取ります。

編集

質問が表示されました。Popenオブジェクトからstdoutパイプを取得するだけです。

cat = subprocess.Popen(["hadoop", "fs", "-cat", "/path/to/myfile"], stdout=subprocess.PIPE)
for line in cat.stdout:
    print line
37
Keith Randall

外部の依存関係を追加することを避けたい場合、キースの答えが道です。 Pydoop 、一方で、あなたの人生をもっと楽にすることができます:

import pydoop.hdfs as hdfs
with hdfs.open('/user/myuser/filename') as f:
    for line in f:
        do_something(line)

あなたの懸念については、Pydoopは積極的に開発されており、長年 CRS4 で本番環境で使用されています。主に計算生物学アプリケーション用です。

シモーネ

28
simleo

過去2年間で、Hadoop-Streamingについて多くの動きがありました。 Clouderaによると、これはかなり高速です: http://blog.cloudera.com/blog/2013/01/a-guide-to-python-frameworks-for-hadoop/ 私はそれで大成功を収めました。

1
Brian Dolan