2012-09-03 26 views
6

Tôi đang sử dụng thư viện Python, Fabric, để thực hiện một số bảo trì máy chủ từ xa. Vải tự động xuất tất cả các câu trả lời cho các lệnh từ xa và cục bộ trừ khi bạn bọc lệnh trong cặp vợ chồng với câu lệnh. Giống như vậy, trên máy tính cục bộ,Cách pythonic để bao bọc một số chức năng giống với câu lệnh

with settings(warn_only='true'): 
    with hide('running', 'stdout', 'stderr', 'warnings'): 
     output = local("uname -a", True) 

hay như thế này trên một máy từ xa:

with settings(warn_only='true'): 
    with hide('running', 'stdout', 'stderr', 'warnings'): 
     output = run("uname -a") 

Tôi viết thư này là một nhiệm vụ lâu dài và phức tạp và thấy mình lặp đi lặp lại hai với báo cáo hơn và hơn nữa . Tôi muốn viết một hàm gọi là _mute() để ngăn chặn sự lặp lại đó. Nó sẽ cho phép tôi làm điều gì đó như thế này:

def _mute(fabric_cmd, args): 
    with settings(warn_only='true'): 
     with hide('running', 'stdout', 'stderr', 'warnings'): 
      output = fabric_cmd(args) 
    return output 

def some_remote_task(): 
    # Run a remote task silently 
    _mute(remote, 'uname -a') 

def some_local_task(): 
    # Run a local task silently 
    _mute(local, 'uname -a', True) 

Tôi đã xem xét một số giải pháp và biết rằng "eval" có thể làm điều này cho tôi. Nhưng mỗi trang tôi đọc về eval cho thấy rằng nó gần như luôn luôn là một ý tưởng tồi vì các vấn đề an ninh. Tôi nhìn vào partials, nhưng tôi không thể tìm ra cách để làm cho một đối số trong chức năng _mute gọi của tôi. Tôi đoán có một khái niệm Python cấp cao hơn mà tôi đang thiếu ở đây. Cách pythonic để làm gì? Cảm ơn mọi hướng bạn có thể cung cấp.

Trả lời

11

Giải pháp tốt hơn là bạn nên xây dựng trình quản lý ngữ cảnh của riêng mình; do sự xa cách dễ nhất là nên sử dụng các contextlib.contextmanager decorator:

from contextlib import contextmanager 

@contextmanager 
def _mute(): 
    with settings(warn_only='true'): 
     with hide('running', 'stdout', 'stderr', 'warnings'): 
      yield 

Sau đó sử dụng _mute như một người quản lý bối cảnh:

def some_remote_task(): 
    # Run a remote task silently 
    with _mute(): 
     output = remote("uname -a") 

này là rất nhiều nhỏ gọn hơn và dễ đọc vì phải gõ lại bối cảnh hai lớn hơn dòng quản lý và có thêm lợi thế mà bây giờ bạn có thể chạy nhiều lệnh trong cùng một ngữ cảnh đó.

Đối với câu hỏi của bạn; bạn có thể dễ dàng áp dụng đối số tùy ý để một chức năng nhất định bằng cách sử dụng cú pháp *args:

def _mute(fabric_cmd, *args): 
    with settings(warn_only='true'): 
     with hide('running', 'stdout', 'stderr', 'warnings'): 
      return fabric_cmd(*args) 

def some_remote_task(): 
    # Run a remote task silently 
    output = _mute(remote, 'uname -a') 

Xem *args and **kwargs? để biết thêm thông tin về đối số tùy ý *args liệt kê thủ đoạn.

+0

Nhờ trang trí @contextmanager hoạt động hoàn hảo. Tôi đánh giá cao bạn hướng dẫn tôi đối với các tài liệu cho những người cũng như cú pháp * args. –

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