web-dev-qa-db-fra.com

Python lire le fichier en tant que flux depuis HDFS

Voici mon problème: j'ai un fichier en HDFS qui peut potentiellement être énorme (= pas assez pour tout mettre en mémoire)

Ce que je voudrais faire, c'est éviter d'avoir à mettre ce fichier en cache, et ne le traiter que ligne par ligne comme je le ferais avec un fichier normal:

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

Je cherche à voir s'il existe un moyen facile de faire cela correctement sans utiliser de bibliothèques externes. Je peux probablement le faire fonctionner avec libpyhdfs ou python-hdfs mais j'aimerais si possible éviter d'introduire de nouvelles dépendances et des bibliothèques non testées dans le système, d'autant plus que ces deux ne semblent pas fortement entretenus et déclarent qu'ils ne devraient pas être utilisés dans la production.

Je pensais faire cela en utilisant les outils de ligne de commande "hadoop" standard en utilisant le module Python subprocess, mais je n'arrive pas à faire ce dont j'ai besoin depuis il n'y a pas d'outils de ligne de commande qui feraient mon traitement et je voudrais exécuter une fonction Python pour chaque ligne en mode streaming).

Existe-t-il un moyen d'appliquer Python fonctionne comme les opérandes droits des canaux en utilisant le module de sous-processus? Ou encore mieux, l'ouvrir comme un fichier en tant que générateur afin que je puisse traiter chaque ligne facilement?

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

S'il existe un autre moyen de réaliser ce que j'ai décrit ci-dessus sans utiliser de bibliothèque externe, je suis également assez ouvert.

Merci pour toute aide !

24
Charles Menguy

Vous voulez xreadlines , il lit les lignes d'un fichier sans charger le fichier entier en mémoire.

Modifier :

Maintenant, je vois votre question, il vous suffit d'obtenir le tuyau stdout de votre objet Popen:

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

Si vous voulez éviter d'ajouter des dépendances externes à tout prix, la réponse de Keith est la voie à suivre. Pydoop , d'autre part, pourrait vous faciliter la vie:

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

Concernant vos préoccupations, Pydoop est activement développé et a été utilisé en production pendant des années à CRS4 , principalement pour des applications de biologie computationnelle.

Simone

28
simleo

Au cours des deux dernières années, il y a eu beaucoup de mouvement sur Hadoop-Streaming. C'est assez rapide selon Cloudera: http://blog.cloudera.com/blog/2013/01/a-guide-to-python-frameworks-for-hadoop/ J'ai eu du bon succès avec elle.

1
Brian Dolan