2013-08-09 21 views
10

Tôi có một công việc MapReduce quy định tại main.py, mà nhập khẩu các mô-đun lib từ lib.py. Tôi sử dụng Hadoop Streaming để nộp công việc này đến cụm Hadoop như sau:Cách nhập mô-đun tùy chỉnh trong công việc MapReduce?

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 

Trong hiểu biết của tôi, điều này sẽ đưa cả hai main.pylib.py vào phân phối thư mục bộ nhớ cache trên mỗi máy tính và do đó làm cho mô-đun lib sẵn đến main. Nhưng nó không xảy ra: từ nhật ký tôi thấy rằng các tệp thực sự được sao chép vào cùng một thư mục, nhưng main không thể nhập lib, ném ImportError.

Tại sao điều này xảy ra và làm cách nào để khắc phục sự cố?

UPD. Thêm thư mục hiện hành với con đường đã không làm việc:

import sys  
sys.path.append(os.path.realpath(__file__)) 
import lib 
# ImportError 

dù, tải các module bằng tay đã làm các trick:

import imp 
lib = imp.load_source('lib', 'lib.py') 

Nhưng đó không phải là những gì tôi muốn. Vậy tại sao trình thông dịch Python thấy các tệp .py khác trong cùng một thư mục, nhưng không thể nhập chúng? Lưu ý rằng tôi đã thử thêm một tệp __init__.py trống vào cùng một thư mục mà không có hiệu lực.

+0

Bạn đã kiểm tra 'sys.path' trong' main.py' để đảm bảo thư mục hoạt động được bao gồm chưa? – lmjohns3

+0

@ lmjohns3: vâng, thư mục làm việc nằm trên đường dẫn lớp. BTW, nó không tự động được bao gồm cho chạy script? (chỉ tò mò) – ffriend

+0

Tôi tin điều đó đúng với các tập lệnh Python được bắt đầu trên dòng lệnh, nhưng luồng Hadoop có thể bắt đầu một trình thông dịch Python theo một cách khác (không thực sự chắc chắn). Dù bằng cách nào, tôi vẫn nghĩ rằng điều này nghe có vẻ giống như một vấn đề đường dẫn. Xem http://www.litfuel.net/plush/?postid=195 để có thể phân phối các mô-đun của bạn theo cách khác. Ngoài ra, hãy thử viết các lệnh của bạn vào một kịch bản lệnh shell và truyền nó cho các đối số dòng lệnh '-mapper' và' -reducer'. – lmjohns3

Trả lời

12

Tôi đã đăng câu hỏi lên danh sách người dùng Hadoop và cuối cùng đã tìm thấy câu trả lời. Nó chỉ ra rằng Hadoop không thực sự sao chép các tập tin vào vị trí mà lệnh chạy, mà thay vào đó tạo ra các liên kết tượng trưng cho chúng. Python, đến lượt nó, không thể làm việc với các liên kết tượng trưng và do đó không nhận ra lib.py là mô-đun Python.

Simple workaround ở đây là để đưa cả hai main.pylib.py vào cùng một thư mục, do đó liên kết tượng trưng đến thư mục được đặt vào thư mục làm việc MR công việc, trong khi cả hai tập tin có thể chất trong cùng thư mục. Vì vậy, tôi đã làm như sau:

  1. Đặt main.pylib.py vào app thư mục.
  2. Trong main.py tôi đã sử dụng lib.py trực tiếp, nghĩa là, chuỗi nhập khẩu chỉ là

    nhập khẩu lib

  3. Tải Lên app thư mục với -files tùy chọn.

Vì vậy, lệnh cuối cùng trông như thế này:

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 
+0

Sử dụng tùy chọn -files để tải lên hàng tá tệp không hoạt động trong môi trường hadoop của tôi. –

3

Khi Hadoop-streaming bắt đầu kịch bản python, đường dẫn script python của bạn là nơi mà các tập tin kịch bản thực sự là. Tuy nhiên, hadoop bắt đầu chúng ở './', và lib.py của bạn (đó là một liên kết tượng trưng) cũng ở './'. Vì vậy, hãy cố gắng thêm 'sys.path.append ("./")' trước khi bạn nhập lib.py như thế này: import sys sys.path.append('./') import lib

+0

Tôi đang sử dụng sợi, dường như không hỗ trợ các tệp như các câu trả lời đã chọn. Điều này làm việc tuyệt vời, cảm ơn! – bkribbs

1

Các -files-archive tắc chỉ là phím tắt để distributed cache (DC) Hadoop, một hơn cơ chế chung cũng cho phép tải lên và tự động giải nén lưu trữ ở định dạng zip, tar và tgz/tar.gz. Nếu thay vì bởi một mô-đun duy nhất, thư viện của bạn được triển khai bởi gói Python có cấu trúc, tính năng thứ hai là những gì bạn muốn.

Chúng tôi đang trực tiếp hỗ trợ này trong Pydoop kể từ khi phát hành 1.0.0-rc1, nơi bạn có thể dễ dàng xây dựng một kho lưu trữ mypkg.tgz và chạy chương trình của bạn như:

pydoop submit --upload-archive-to-cache mypkg.tgz [...] 

Các tài liệu có liên quan đang ở http://crs4.github.io/pydoop/self_contained.html và đây là một ví dụ làm việc đầy đủ (yêu cầu wheel): https://github.com/crs4/pydoop/tree/master/examples/self_contained.

Các vấn đề liên quan