2012-01-23 23 views
13

Tôi đang cố gắng tạo tập lệnh đang sử dụng mô-đun đa xử lý với python. Kịch bản lệnh (cho phép gọi nó là myscript.py) sẽ nhận được đầu vào từ một tập lệnh khác có đường ống.Có cách nào để vượt qua 'stdin' như là một đối số cho một quá trình trong python?

Giả sử rằng tôi gọi các tập lệnh như thế này;

$ python writer.py | python myscript.py 

Và đây là mã;

// writer.py 
import time, sys 

def main(): 
    while True: 
     print "test" 
     sys.stdout.flush() 
     time.sleep(1) 

main() 

//myscript.py 
def get_input(): 
    while True: 
     text = sys.stdin.readline() 
     print "hello " + text 
     time.sleep(3) 

if __name__ == '__main__':   
    p1 = Process(target=get_input, args=()) 
    p1.start() 

điều này rõ ràng là không hoạt động, vì đối tượng sys.stdin khác với quy trình chính và p1. Vì vậy, tôi đã cố gắng giải quyết vấn đề này,

//myscript.py 
def get_input(temp): 
    while True: 
     text = temp.readline() 
     print "hello " + text 
     time.sleep(3) 

if __name__ == '__main__':   
    p1 = Process(target=get_input, args=(sys.stdin,)) 
    p1.start() 

nhưng tôi gặp phải lỗi này;

Process Process-1: 
Traceback (most recent call last): 
    File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap 
    self.run() 
    File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run 
    self._target(*self._args, **self._kwargs) 
    File "in.py", line 12, in get_input 
    text = temp.readline() 
ValueError: I/O operation on closed file 

Vì vậy, tôi đoán rằng tệp stdin chính đã đóng và tôi không thể đọc từ tệp đó. Tại kết hợp này, làm thế nào tôi có thể chuyển tập tin stdin của chính vào một tiến trình khác? Nếu đi qua stdin là không thể, làm thế nào tôi có thể sử dụng stdin chính từ một quá trình khác?

cập nhật: OK, tôi cần làm rõ câu hỏi của mình vì mọi người nghĩ rằng việc sử dụng đa xử lý không thực sự cần thiết. xem xét myscript.py như thế này;

//myscript.py 
def get_input(): 
    while True: 
     text = sys.stdin.readline() 
     print "hello " + text 
     time.sleep(3) 

def do_more_things(): 
    while True: 
     #// some code here 
     time.sleep(60*5) 

if __name__ == '__main__':   
    p1 = Process(target=get_input, args=()) 
    p1.start() 

    do_more_things() 

vì vậy, tôi thực sự cần chạy hàm get_input() song song với hàm chính (hoặc các quy trình phụ khác). Xin lỗi vì những xung đột, tôi có tiếng Anh tốt, và tôi đoán tôi không thể rõ ràng về câu hỏi này. Tôi sẽ đánh giá cao nếu các bạn có thể cho tôi biết nếu tôi có thể sử dụng các quy trình chính đối tượng STDIN trong quá trình khác.

cảm ơn trước.

+1

bạn có thể viết thư cho stdin sử dụng cú pháp tìm thấy ở đây http://stackoverflow.com/questions/ 8880461/python-subprocess-output-to-list-or-file/8880555 # 8880555 Ở đó nó được sử dụng để đọc nhưng bạn có thể sử dụng cùng một đối tượng –

+0

Tại sao 'myscript.py' tạo một tiến trình con? Tại sao nó không chỉ đơn giản là đọc từ sys.stdin? Nếu nó đọc từ 'sys.stdin' thì script shell sẽ hoạt động hoàn hảo. Tại sao tạo một tiến trình con? –

+0

Hi S.Lott, Đây chỉ là một nguyên mẫu của vấn đề của tôi, myscript.py chứa một quy trình khác có vòng lặp vô hạn và chạy như một daemon, vì vậy tôi không thể đọc nó trong quá trình chính myscript vì writer.py cũng vô hạn và cần được chạy như một daemon. @JohanLundberg, cảm ơn lời khuyên của bạn, tôi sẽ kiểm tra. –

Trả lời

9

Điều đơn giản nhất là để trao đổi get_input()do_more_things() tức, đọc sys.stdin trong quá trình cha mẹ:

def get_input(stdin): 
    for line in iter(stdin.readline, ''): 
     print("hello", line, end='') 
    stdin.close() 

if __name__ == '__main__': 
    p1 = mp.Process(target=do_more_things) 
    p1.start() 
    get_input(sys.stdin) 

Điều tốt nhất tiếp theo là sử dụng Thread() thay vì.210 cho get_input():

if __name__ == '__main__': 
    t = Thread(target=get_input, args=(sys.stdin,)) 
    t.start() 
    do_more_things() 

Nếu ở trên không giúp bạn có thể thử os.dup():

newstdin = os.fdopen(os.dup(sys.stdin.fileno())) 
try: 
    p = Process(target=get_input, args=(newstdin,)) 
    p.start()  
finally: 
    newstdin.close() # close in the parent 
do_more_things() 
+0

mặc dù tôi chỉ cần thứ ba, các giải pháp khác khá hiệu quả. cảm ơn vì đã dành thời gian và giúp đỡ toàn diện. –

2

Mỗi quy trình mới được tạo bằng mô-đun đa xử lý sẽ có PID riêng, và do đó nó là thiết bị đầu vào tiêu chuẩn và thiết bị đầu ra, ngay cả khi cả hai đều ghi vào cùng một thiết bị đầu cuối, do đó cần phải có khóa.

Bạn đã tạo hai quy trình bằng cách tách nội dung thành hai tập lệnh và tạo quy trình thứ ba với get_input(). get_input có thể đọc đầu vào tiêu chuẩn nếu nó là một luồng thay vì một tiến trình. Sau đó, không cần phải có một chức năng ngủ trong người đọc.

## reader.py 
from threading import Thread 
import sys 

def get_input(): 
    text = sys.stdin.readline() 
    while len(text) != 0: 
     print 'hello ' + text 
     text = sys.stdin.readline() 

if __name__ == '__main__': 
    thread = Thread(target=get_input) 
    thread.start() 
    thread.join() 
2

Đây sẽ chỉ là câu trả lời một phần - vì tôi không rõ ràng về các phần tiếp theo của câu hỏi.

Bạn bắt đầu bằng cách nói rằng bạn dự đoán gọi script của bạn:

$ python writer.py | python myscript.py 

Nếu bạn đang đi để làm điều đó, tác giả cần phải viết tiêu chuẩn ra và myscript cần phải đọc từ đầu vào tiêu chuẩn. Tập lệnh thứ hai sẽ trông giống như sau:

def get_input(): 
    while True: 
     text = sys.stdin.readline() 
     print "hello " + text 
     time.sleep(3) 
if __name__ == '__main__':  
    get_input() 

Không cần xử lý đa. Đối tượng xử lý ...bạn đang kích hoạt hai quy trình từ dòng lệnh - và bạn đang sử dụng trình bao để kết nối chúng với một ống (ẩn danh) (ký tự "|") kết nối đầu ra tiêu chuẩn từ tập lệnh đầu tiên đến đầu vào tiêu chuẩn từ thứ hai kịch bản.

Điểm của đối tượng Quy trình là quản lý khởi chạy quy trình thứ hai từ lần đầu tiên. Bạn cần xác định một quy trình; sau đó bắt đầu nó - sau đó bạn có thể muốn chờ đợi cho đến khi nó đã chấm dứt trước khi thoát khỏi quá trình đầu tiên ... (gọi p1.join() sau p1.start() sẽ đủ cho điều này).

Nếu bạn muốn liên lạc giữa một cặp quy trình dưới điều khiển python, có thể bạn sẽ muốn sử dụng đối tượng multiprocess.Pipe để thực hiện việc này. Sau đó bạn có thể dễ dàng giao tiếp giữa bộ phận sinh dục và quá trình sinh sản cấp dưới bằng cách đọc và ghi vào/từ đối tượng Ống thay vì đầu vào tiêu chuẩn và đầu ra tiêu chuẩn. Nếu bạn thực sự muốn tái đầu vào tiêu chuẩn và đầu ra tiêu chuẩn, điều này có thể là do rối tung với các trình mô tả tệp mức thấp và/hoặc bằng cách ghi đè/thay thế các đối tượng sys.stdin và sys.stdout ... nhưng, tôi nghi ngờ , có thể bạn không muốn (hoặc cần) để làm điều này.

1

Để đọc các đường ống được sử dụng đầu vào fileinput:

myscript.py

import fileinput 

if __name__ == '__main__': 
    for line in fileinput.input(): 
     #do stuff here 
     process_line(line) 
Các vấn đề liên quan