2009-06-09 36 views
11

im đẻ trứng một kịch bản chạy trong một thời gian dài từ một ứng dụng web như thế này:quá trình sinh sản từ python

os.spawnle(os.P_NOWAIT, "../bin/producenotify.py", "producenotify.py", "xx",os.environ) 

kịch bản được sinh ra thành công và nó chạy, nhưng cho đến khi nó được hơn tôi không thể miễn phí cổng được ứng dụng web sử dụng hoặc nói cách khác là tôi không thể khởi động lại ứng dụng web. làm thế nào để tôi sinh ra một quá trình và làm cho nó hoàn toàn độc lập với các ứng dụng web?

đây là trên os linux.

+1

Tại sao bạn không sử dụng tiến trình con. Mở để thực hiện việc này? –

+2

S. Lott: tôi sẽ có thể giết/khởi động lại quá trình ứng dụng web/cha mẹ sau khi thực hiện subprocess.Popen? cảm ơn – mark

Trả lời

26

Khi @mark làm rõ đó là hệ thống Linux, tập lệnh có thể dễ dàng tự hoàn toàn độc lập, tức là, daemon, bằng cách làm theo recipe này. (Bạn cũng có thể làm điều đó trong phụ huynh sau os.fork và chỉ sau đó os.exec... quy trình con).

Chỉnh sửa: để làm rõ một số chi tiết nhận xét của wrt @ mark về câu trả lời của tôi: các đặc quyền siêu người dùng không cần thiết để "daemonize" quy trình theo công thức nấu ăn, cũng không cần thay đổi thư mục làm việc hiện tại mã trong công thức làm điều đó và hơn thế nữa, đó không phải là phần quan trọng - đúng hơn là chuỗi logic hợp lý của các cuộc gọi fork, _exitsetsid). Các biến thể os.exec... khác nhau làm không kết thúc bằng e sử dụng môi trường của quy trình gốc, do đó phần cũng dễ dàng - xem Python online docs.

Để giải quyết các đề xuất được đưa ra trong nhận xét và câu trả lời của người khác: Tôi tin rằng subprocessmultiprocessing mỗi lần không làm daemon quá trình con, có vẻ như những gì @mark cần; kịch bản có thể tự thực hiện, nhưng vì một số mã phải hoạt động fork s và setsid, có vẻ như tôi giữ cho tất cả sinh sản trên mặt phẳng cấp thấp hơn là trộn một số cấp cao và một số thấp mã cấp trong quá trình hoạt động. Dưới đây là một phiên bản rút gọn và đơn giản hóa của công thức tại URL trên, được thiết kế để được gọi trong cha mẹ để sinh ra một daemon - theo cách này, mã có thể được sử dụng để thực thi các thực thi không phải Python cũng như vậy. . Như đã nêu, mã phải đáp ứng nhu cầu @mark giải thích, tất nhiên nó có thể được điều chỉnh theo nhiều cách - tôi khuyên bạn nên đọc công thức gốc và các bình luận và thảo luận của nó, cũng như những cuốn sách mà nó đề xuất, để biết thêm thông tin.

import os 
import sys 

def spawnDaemon(path_to_executable, *args) 
    """Spawn a completely detached subprocess (i.e., a daemon). 

    E.g. for mark: 
    spawnDaemon("../bin/producenotify.py", "producenotify.py", "xx") 
    """ 
    # fork the first time (to make a non-session-leader child process) 
    try: 
     pid = os.fork() 
    except OSError, e: 
     raise RuntimeError("1st fork failed: %s [%d]" % (e.strerror, e.errno)) 
    if pid != 0: 
     # parent (calling) process is all done 
     return 

    # detach from controlling terminal (to make child a session-leader) 
    os.setsid() 
    try: 
     pid = os.fork() 
    except OSError, e: 
     raise RuntimeError("2nd fork failed: %s [%d]" % (e.strerror, e.errno)) 
     raise Exception, "%s [%d]" % (e.strerror, e.errno) 
    if pid != 0: 
     # child process is all done 
     os._exit(0) 

    # grandchild process now non-session-leader, detached from parent 
    # grandchild process must now close all open files 
    try: 
     maxfd = os.sysconf("SC_OPEN_MAX") 
    except (AttributeError, ValueError): 
     maxfd = 1024 

    for fd in range(maxfd): 
     try: 
      os.close(fd) 
     except OSError: # ERROR, fd wasn't open to begin with (ignored) 
      pass 

    # redirect stdin, stdout and stderr to /dev/null 
    os.open(os.devnull, os.O_RDWR) # standard input (0) 
    os.dup2(0, 1) 
    os.dup2(0, 2) 

    # and finally let's execute the executable for the daemon! 
    try: 
     os.execv(path_to_executable, args) 
    except Exception, e: 
     # oops, we're cut off from the world, let's just give up 
     os._exit(255) 
+0

alex, đó là một hệ thống giống như Unix. fedora linux. ứng dụng web không có đặc quyền người dùng siêu. đó có phải là vấn đề không? cũng daemon nên có cùng một thư mục làm việc và các biến môi trường như webapp. làm thế nào để tôi đạt được những điều này? cảm ơn – mark

+0

để tôi chỉnh sửa câu trả lời của mình để thêm các thông tin này. –

+0

alex, tx để làm rõ. tôi đã kiểm tra công thức và hơi khó hiểu. mã đó có trong ứng dụng web chính không? hay nó sẽ đi trong kịch bản mới được sinh ra? cảm ơn rất nhiều lần nữa! – mark

12

Bạn có thể sử dụng thư viện đa xử lý để sinh ra quy trình. Ví dụ cơ bản được hiển thị ở đây:

from multiprocessing import Process 

def f(name): 
    print 'hello', name 

if __name__ == '__main__': 
    p = Process(target=f, args=('bob',)) 
    p.start() 
    p.join() 
+0

+1 đa xử lý pythonic! – SingleNegationElimination

+6

điều này có vấn đề là quá trình chính không thể bị giết cho đến khi tiến trình con được thực hiện. cảm ơn! – mark

+0

* Lưu ý * thư viện 'multiprocessing' đã được thêm vào Python 2.6. Đây là tài liệu http://docs.python.org/library/multiprocessing.html – Ciantic

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