python - with - map reduce
¿Cómo importar un módulo personalizado en un trabajo de MapReduce? (3)
Publiqué la pregunta en la lista de usuarios de Hadoop y finalmente encontré la respuesta. Resulta que Hadoop realmente no copia archivos a la ubicación donde se ejecuta el comando, sino que crea enlaces simbólicos para ellos. Python, por su parte, no puede trabajar con enlaces simbólicos y, por lo tanto, no reconoce lib.py
como módulo de Python.
Una solución simple aquí es colocar tanto main.py
como lib.py
en el mismo directorio, de modo que el enlace simbólico al directorio se coloque en el directorio de trabajo de MR, mientras que ambos archivos están físicamente en el mismo directorio. Entonces hice lo siguiente:
- Coloque
main.py
ylib.py
en el directorio de laapp
. En
main.py
utilicélib.py
directamente, es decir, la cadena de importación es soloimportación lib
El directorio de la
app
-files
con la opción-files
.
Entonces, el comando final se ve así:
hadoop jar /usr/lib/hadoop-mapreduce/hadoop-streaming.jar -files app
-mapper "app/main.py map" -reducer "app/main.py reduce"
-input input -output output
Tengo un trabajo de MapReduce definido en main.py
, que importa el módulo lib
de lib.py
Uso Hadoop Streaming para enviar este trabajo al clúster de Hadoop de la siguiente manera:
hadoop jar /usr/lib/hadoop-mapreduce/hadoop-streaming.jar -files lib.py,main.py
-mapper "./main.py map" -reducer "./main.py reduce"
-input input -output output
Según entiendo, esto debería incluir tanto main.py
como lib.py
en la carpeta de caché distribuida en cada máquina informática y, por lo tanto, hacer que el módulo lib
esté disponible para main
. Pero no sucede: del registro veo que los archivos están realmente copiados en el mismo directorio, pero main
no puede importar lib
, lanzando ImportError
.
¿Por qué sucede esto y cómo puedo solucionarlo?
UPD. Agregar el directorio actual a la ruta no funcionó:
import sys
sys.path.append(os.path.realpath(__file__))
import lib
# ImportError
sin embargo, cargar el módulo manualmente hizo el truco:
import imp
lib = imp.load_source(''lib'', ''lib.py'')
Pero eso no es lo que quiero. Entonces, ¿por qué el intérprete de Python ve otros archivos .py
en el mismo directorio, pero no puede importarlos? Tenga en cuenta que ya he intentado agregar un archivo __init__.py
vacío al mismo directorio sin efecto.
Cuando Hadoop-Streaming inicia los scripts de python, la ruta de su script de python es donde realmente está el archivo de script. Sin embargo, hadoop los inicia en ''./'', y tu lib.py (es un enlace simbólico) está en ''./'', también. Por lo tanto, intente agregar ''sys.path.append ("./")'' antes de importar lib.py de la siguiente manera: import sys sys.path.append(''./'') import lib
Los -archive
y -archive
son solo accesos directos a la memoria caché distribuida (DC) de Hadoop, un mecanismo más general que también permite cargar y descomprimir archivos automáticamente en los formatos zip, tar y tgz / tar.gz. Si en lugar de un solo módulo su biblioteca está implementada por un paquete estructurado de Python, la última característica es la que usted desea.
Estamos apoyando esto directamente en Pydoop desde la versión 1.0.0-rc1, donde puedes simplemente crear un archivo mypkg.tgz
y ejecutar tu programa como:
pydoop submit --upload-archive-to-cache mypkg.tgz [...]
Los documentos relevantes están en http://crs4.github.io/pydoop/self_contained.html y aquí hay un ejemplo completo de trabajo (requiere rueda ): https://github.com/crs4/pydoop/tree/master/examples/ self_contained .