2015-10-20 21 views
6

Có nhiều ví dụ về cách thực hiện những việc sau:Giao tiếp chương trình trong python trên Linux

1) Giao tiếp giữa các quá trình khác nhau trong cùng một chương trình.

2) Giao tiếp giữa client/server thông qua mạng

Tuy nhiên, câu hỏi này không có ví dụ điển hình bất cứ nơi nào tôi đã xem xét:

  • là gì một cách kinh điển để gửi một chuỗi từ trăn chương trình A đến chương trình B, mà khối và xử lý chuỗi này và sau đó chờ đợi cho nhau trong một vòng lặp?

Tôi cảm thấy như tôi đã đến gần câu trả lời nhiều lần, nhưng chưa bao giờ quản lý để tạo một ví dụ làm việc.

yêu cầu ngụ ý khác:

  • Thực ra hai chương trình khác nhau: ví dụ cần phải thực sự có hai chương trình khác nhau (tức là hai tập tin progA.py, progB.py mà có thể chạy riêng biệt từ dòng lệnh trong hai màn hình trên cùng một máy), không sử dụng bất kỳ loại forking hoặc multiprocess nào để tạo máy khách và máy chủ.
  • Vui lòng đề xuất cách thực hiện điều này cho phép các chuỗi có giới hạn độ dài thay đổi có thời lượng hợp lý được gửi, thay vì phải nhận số byte chính xác của kích thước dữ liệu chính xác. (Sau này là nhiều hơn nữa dễ bị lỗi trong thực hiện).
  • Lý tưởng nhất là làm điều này mà không cần sử dụng kết nối Internet cục bộ

Ví dụ; khi người đọc sử dụng:

pipein = open(pipe_name, 'r') 
while program.KeepRunning: 
    action = pipein.readline()[:-1] 
    program.processLine(line) 
    time.sleep(1) 

và nhà văn sử dụng:

command = "enable" 
pipeout = os.open(pipe_name, os.O_WRONLY) 
os.write(pipeout, command) 
os.write(pipeout, "\n") 

như được đề nghị tại http://www.python-course.eu/pipes.php người đọc bị mắc kẹt trong một vòng lặp vô hạn cách đọc to các chuỗi rỗng.

Điều thú vị là thêm if(action == 'enable'): longFunction() vào các kết quả chức năng program.processLine trong một phần của mã trong longFunction được thực thi trước khi bị kẹt đọc ra dòng trống mãi mãi.

Mặt khác, tất cả các ví dụ sử dụng mô đun subprocess mức thấp hơn hiện đại hơn chỉ liên quan đến các ứng dụng đa luồng chứ không phải nhiều ứng dụng. Triển khai khác liên quan đến ổ cắm và mạng.

Trong khi tôi đã thử sử dụng ổ cắm, điều này dẫn đến lỗi chung 'đã xảy ra lỗi' với nhiều nguyên nhân có thể xảy ra Error 111: “connection refused” hiển thị 'một số thời gian'. Là một phần của mã python được thực hiện khi nhận được một số lệnh thực sự thay đổi cấu hình mạng (ví dụ: nó gọi các lệnh như ip, tciptables với các đối số khác nhau) sử dụng kết nối mạng tới localhost là điều có thể tránh được. để gỡ lỗi và các vấn đề thường khó chịu. Bên cạnh phần không cần thiết khi chương trình thứ hai chạy trên cùng một máy, vì vậy bất kỳ liên lạc chương trình liên thông nào cũng không cần phải sử dụng các giao diện mạng.

+0

bạn đã thử [multiprocessing.Queue] (https://pymotw.com/2/multiprocessing/communication.html) – Pynchia

Trả lời

2

Đó là hành vi dự định. Hãy xem this answer cho vấn đề tương tự và tổng quan về hành vi FIFO. Phần có liên quan cho câu hỏi của bạn là:

Khi không có người viết (...) độc giả nào được thông báo về điều đó thông qua read() trả lại EOF.

Các file.readline()docs nói rằng '' (chuỗi rỗng) có nghĩa là, rằng EOF đạt được:

nếu f.readline() lợi nhuận một chuỗi rỗng, kết thúc của tập tin đã đạt được, trong khi một dòng trống là được đại diện bởi '\n', một chuỗi chỉ chứa một dòng mới.

Vậy đó. Trong vòng lặp vô hạn trên mỗi lần đọc, bạn nhận được một chuỗi rỗng, cho biết không có nhiều người viết nào được kết nối.

Không có gì ngăn cản bạn sử dụng các đường ống có tên để giải quyết công việc của bạn. Cách đơn giản nhất là ngủ một lúc, khi không có người viết. Dưới đây là ví dụ làm việc:

# server.py 

import os 
import time 

pipe_name = 'pipe_test' 

if not os.path.exists(pipe_name): 
    os.mkfifo(pipe_name) 

with open(pipe_name, 'r') as pipe: 
    print("Listening for actions...") 
    while True: 
     action = pipe.readline()[:-1] 
     if action == '': 
      print("No clients. Sleeping...") 
      time.sleep(1) 
     else: 
      print("Action received:", repr(action)) 
# client.py 

import os 

pipe_name = 'pipe_test' 

if not os.path.exists(pipe_name): 
    os.mkfifo(pipe_name) 

print("Waiting for server to start...") 
with open(pipe_name, 'w') as pipe: 
    action = input("Enter action to send: ") 
    pipe.write(action + '\n') 

Ghi chú:

  • Không có điểm trong việc sử dụng os.open(), đó là chức năng ở mức độ thấp. Bạn có thể sử dụng open() để tương tác với các đường ống có tên.
  • Mở ống có tên để đọc blocks cho đến khi người viết đầu tiên được kết nối. Vì vậy, bạn sẽ không thấy Listening for actions... trong đầu ra, cho đến khi khách hàng đầu tiên được kết nối với đường ống. Cũng vậy với nhà văn bắt đầu mà không có độc giả.
  • Bạn đã yêu cầu "chặn và xử lý chuỗi này và sau đó đợi chuỗi khác trong vòng lặp". Trừ khi bạn đang xử lý chuỗi trong chuỗi riêng biệt, nó sẽ không cố đọc chuỗi tiếp theo cho đến khi chuỗi hiện tại được xử lý.
+0

Câu trả lời hay. Một điều: Tại sao '[: -1]' lại được sử dụng? Nếu tôi hiểu chính xác, nếu nhiều hơn một dòng được thêm vào đường ống của khách hàng (s) trong khi máy chủ đang ngủ chỉ cuối cùng của những dòng được đọc. – aphid

+0

'f.readline()' trả về dòng có dấu '\ n', vì vậy '[: -1]' được sử dụng để tách '\ n' này khỏi cuối chuỗi. Không, tất cả các dòng được thêm vào trong khi ngủ sẽ được xử lý, khi quá trình thức dậy. Bạn có thể kiểm tra nó bằng cách tăng thời gian ngủ và gửi nhiều dòng trong thời gian ngủ. Ống lưu trữ tất cả các dòng trong khi máy chủ ngủ. –

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