2011-12-06 86 views
5

Tôi có một chương trình chạy dài có thể có 4 quy trình, nhưng có thể được cấu hình để có nhiều hơn. Tôi đã nghiên cứu logging from multiple processes bằng cách sử dụng số logging của python và đang sử dụng phương pháp SocketHandler được thảo luận here. Tôi không bao giờ có bất kỳ vấn đề có một logger duy nhất (không có ổ cắm), nhưng từ những gì tôi đọc tôi đã nói với nó sẽ thất bại cuối cùng và bất ngờ. Theo như tôi hiểu nó không biết điều gì sẽ xảy ra khi bạn cố gắng viết vào cùng một tập tin cùng một lúc. Mã của tôi về cơ bản nào sau đây:Ghi nhật ký bằng Python từ nhiều quá trình

import logging 
log = logging.getLogger(__name__) 

def monitor(...): 
    # Spawn child processes with os.fork() 
    # os.wait() and act accordingly 

def main(): 
    log_server_pid = os.fork() 
    if log_server_pid == 0: 
     # Create a LogRecordSocketServer (daemon) 
     ... 
     sys.exit(0) 
    # Add SocketHandler to root logger 
    ... 
    monitor(<configuration stuff>) 

if __name__ == "__main__": 
    main() 

Vì vậy, câu hỏi của tôi là: Tôi có cần phải tạo ra một đối tượng log mới sau mỗi os.fork()? Điều gì sẽ xảy ra với đối tượng toàn cầu hiện tại log?

Khi thực hiện công việc theo cách của tôi, tôi có gặp phải vấn đề mà tôi đang cố tránh (nhiều tệp/ổ cắm mở) không? Điều này sẽ thất bại và tại sao nó sẽ thất bại (Tôi muốn có thể biết được các triển khai tương tự trong tương lai sẽ thất bại)?

Ngoài ra, phương pháp ghi "bình thường" (một log=) biểu thức ghi vào một tệp từ nhiều quy trình không thành công? Nó có làm tăng IOError/OSError không? Hay nó không hoàn toàn ghi dữ liệu vào tập tin?

Nếu ai đó có thể cung cấp câu trả lời hoặc liên kết để giúp tôi, điều đó thật tuyệt. Cảm ơn.

FYI: Tôi đang thử nghiệm trên Mac OS X Lion và mã có thể sẽ chạy trên CentOS 6 VM trên máy Windows (nếu vấn đề đó). Bất kỳ giải pháp nào tôi sử dụng không cần phải làm việc trên Windows, nhưng nên làm việc trên một hệ thống dựa trên Unix.

CẬP NHẬT: Câu hỏi này đã bắt đầu di chuyển khỏi việc ghi nhật ký hành vi cụ thể và nhiều hơn trong lĩnh vực Linux làm gì với bộ mô tả tệp trong nhánh. Tôi rút ra một cuốn sách giáo khoa đại học và có vẻ như nếu bạn mở một tệp ở chế độ chắp thêm từ hai quy trình (không phải trước một ngã ba) thì cả hai đều có thể ghi vào tệp đúng với điều kiện ghi của bạn không vượt quá bộ đệm hạt nhân thực tế (mặc dù dòng đệm có thể cần phải được sử dụng, vẫn không chắc chắn trên đó). Điều này tạo ra 2 mục bảng tập tin và một mục nhập bảng v-nút. Mở một tập tin sau đó forking không phải là nghĩa vụ phải làm việc, nhưng nó có vẻ miễn là bạn không vượt quá bộ đệm hạt nhân như trước (tôi đã thực hiện nó trong một chương trình trước đó). Vì vậy, tôi đoán, nếu bạn muốn nền tảng độc lập đa xử lý đăng nhập bạn sử dụng ổ cắm và tạo ra một SocketHandler mới sau mỗi ngã ba để được an toàn như Vinay đề nghị dưới đây (mà nên làm việc ở khắp mọi nơi). Đối với tôi, vì tôi có quyền kiểm soát mạnh mẽ những gì hệ điều hành phần mềm của tôi đang được chạy, tôi nghĩ rằng tôi sẽ đi với một đối tượng toàn cầu log với một FileHandler (mở trong chế độ phụ thêm theo mặc định và dòng đệm trên hầu hết các hệ điều hành). Tài liệu cho open cho biết "Đệm âm có nghĩa là sử dụng mặc định hệ thống, thường là dòng đệm cho các thiết bị tty và được đệm hoàn toàn cho các tệp khác. Nếu bỏ qua, mặc định hệ thống được sử dụng". hoặc tôi chỉ có thể tạo luồng ghi nhật ký của riêng mình để đảm bảo lưu vào bộ đệm dòng. Và chỉ để được rõ ràng, tôi ok với:

# Process A 
a_file.write("A\n") 
a_file.write("A\n") 
# Process B 
a_file.write("B\n") 

sản xuất ...

A\n 
B\n 
A\n 

miễn là nó không sản xuất ...

AB\n 
\n 
A\n 

Vinay (hoặc bất cứ ai khác), làm thế nào sai tôi là ai? Cho tôi biết. Cảm ơn bạn cho bất kỳ rõ ràng hơn/độ nhạy bạn có thể cung cấp.

+0

Chủ đề và ổ khóa hữu ích cho những việc như thế này ... –

+0

Tôi cần các quy trình riêng biệt vì trẻ em giao tiếp với các thiết bị bên ngoài nên càng nhanh càng tốt. – daveydave400

+0

Tôi đã cập nhật câu trả lời của mình. –

Trả lời

2

Tôi có cần tạo đối tượng nhật ký mới sau mỗi os.fork() không? Điều gì xảy ra với đối tượng đăng nhập toàn cục hiện tại?

AFAIK đối tượng nhật ký chung vẫn trỏ đến cùng một bộ ghi trong quy trình cha và con. Vì vậy, bạn không cần phải tạo một cái mới. Tuy nhiên, tôi nghĩ bạn nên tạo và thêm SocketHandler sau fork() trong monitor(), để máy chủ socket có bốn kết nối riêng biệt, mỗi kết nối cho mỗi quy trình con. Nếu bạn không làm điều này, thì các tiến trình con được chia nhỏ trong màn hình() sẽ kế thừa SocketHandler và tay cầm socket của nó từ cha mẹ của chúng, nhưng tôi không biết chắc chắn rằng nó sẽ hoạt động không đúng. Hành vi có thể phụ thuộc vào hệ điều hành và bạn có thể may mắn trên OSX.

Bằng cách làm mọi thứ theo cách của tôi, tôi thậm chí có gặp vấn đề mà tôi đang cố tránh (nhiều tệp/ổ cắm mở) không? Điều này sẽ thất bại và tại sao nó sẽ thất bại (Tôi muốn có thể biết được các triển khai tương tự trong tương lai sẽ thất bại)?

Tôi không mong đợi thất bại nếu bạn tạo kết nối ổ cắm vào máy chủ socket sau khi tôi đề xuất ở trên, nhưng tôi không chắc chắn hành vi được xác định rõ trong bất kỳ trường hợp nào khác. Bạn tham khảo nhiều tệp đang mở nhưng tôi không thấy tham chiếu đến việc mở tệp trong đoạn mã giả của bạn, chỉ cần mở ổ cắm.

Ngoài ra, phương pháp ghi nhật ký "bình thường" (một log = expression) vào một tệp từ nhiều quy trình không thành công như thế nào? Nó có làm tăng IOError/OSError không? Hay nó không hoàn toàn ghi dữ liệu vào tập tin?

Tôi nghĩ rằng hành vi không được xác định rõ ràng, nhưng người ta mong đợi các phương thức không xuất hiện dưới dạng thông điệp nhật ký xen kẽ từ các quy trình khác nhau trong tệp, ví dụ:

Process A writes first part of its message 
Process B writes its message 
Process A writes second part of its message 

Cập nhật: Nếu bạn sử dụng một FileHandler theo cách bạn mô tả trong bình luận của bạn, mọi thứ sẽ không được tốt như vậy, do kịch bản tôi đã mô tả ở trên: quá trình A và B cả hai bắt đầu chỉ vào phần cuối của tệp (vì chế độ nối thêm), nhưng sau đó mọi thứ có thể không đồng bộ vì (ví dụ trên bộ đa xử lý, nhưng thậm chí có khả năng trên bộ xử lý), một quy trình có thể (trước một cách khác) ghi vào xử lý tệp được chia sẻ trước một quá trình khác đã hoàn thành.

+0

Khi tôi nói nhiều tập tin tôi có nghĩa là nếu tôi đã thực hiện một FileHandler cơ bản thay vì một SocketHandler. Tôi đã nói chuyện với một đồng nghiệp và ông đã đề cập rằng nếu đăng nhập sẽ mở ra một FileHandler trong chế độ phụ thêm trên linux mà tôi nên được ok (một đối tượng đăng nhập, một trình xử lý tệp, nhiều nhánh). Suy nghĩ? Và tạo SocketHandlers sau khi một ngã ba có ý nghĩa. – daveydave400

+0

Tôi đã cập nhật câu hỏi của mình, cảm ơn. – daveydave400

+0

Tôi sẽ chấp nhận câu trả lời của bạn vì việc tạo SocketHandler sau ngã ba, nhưng tôi vẫn không đồng ý với chế độ nối thêm (nhân nên tạo phụ thêm viết nguyên tử). – daveydave400

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