python: có thể đính kèm bảng điều khiển vào một quy trình đang chạy không


81

Tôi chỉ muốn xem trạng thái của quy trình, liệu có thể đính kèm bảng điều khiển vào quy trình hay không, vì vậy tôi có thể gọi các hàm bên trong quy trình và xem một số biến toàn cục.

Tốt hơn là quá trình chạy mà không bị ảnh hưởng (tất nhiên hiệu suất có thể giảm một chút)


7
về cơ bản, một trình gỡ lỗi?
st0le

một cái gì đó giống như trình thông dịch dòng lệnh python.exe
Bin Chen

Câu trả lời:


42

Nếu bạn có quyền truy cập vào mã nguồn của chương trình, bạn có thể thêm chức năng này một cách tương đối dễ dàng.

Xem Công thức 576515 :Debugging a running python process by interrupting and providing an interactive prompt (Python)

Để trích:

Điều này cung cấp mã để cho phép bất kỳ chương trình python nào sử dụng nó bị gián đoạn tại thời điểm hiện tại và được giao tiếp thông qua bảng điều khiển tương tác python bình thường. Điều này cho phép các local, các hình cầu và trạng thái chương trình liên quan được điều tra, cũng như gọi các hàm và lớp tùy ý.

Để sử dụng, một tiến trình sẽ nhập mô-đun và gọi hàm nghe () tại bất kỳ thời điểm nào trong khi khởi động. Để làm gián đoạn quá trình này, tập lệnh có thể được chạy trực tiếp, đưa ra Id tiến trình của quá trình để gỡ lỗi dưới dạng tham số.


Một cách triển khai khác của khái niệm gần giống được cung cấp bởi rconsole . Từ tài liệu:

rconsole là một bảng điều khiển Python từ xa với tính năng tự động hoàn thành, có thể được sử dụng để kiểm tra và sửa đổi không gian tên của một tập lệnh đang chạy.

Để gọi trong một tập lệnh, hãy làm:

from rfoo.utils import rconsole
rconsole.spawn_server()

Để đính kèm từ một trình bao, hãy làm:

$ rconsole

Lưu ý bảo mật: Trình nghe rconsole bắt đầu bằng spawn_server () sẽ chấp nhận bất kỳ kết nối cục bộ nào và do đó có thể không an toàn khi sử dụng trong các môi trường lưu trữ được chia sẻ hoặc tương tự!


2
Đó thực sự là một công thức rất hay. Sử dụng các đường ống và tệp cho đầu vào và đầu ra thực sự thông minh và tôi nghĩ rằng bất kỳ dự án tử tế nào cũng sẽ được hưởng lợi từ chức năng như vậy.
erkmene

2
Tuy nhiên, nó rất không an toàn, vì vậy hãy sử dụng cẩn thận
fmark

Tôi đã thử công thức và nó đã phá vỡ cài đặt python của tôi. 'module' đối tượng không có thuộc tính 'getmro'
Victor 'Chris' Cabral

Tôi đã biên dịch phần mở rộng cython, sau khi thêm phần mở rộng vào mã và khởi động máy chủ rpc, nhưng rconsole sẽ luôn bị hỏng một cách đáng tiếc sau bất kỳ hoạt động nào. rfoo._rfoo.EofError: 0
Sajuuk

60

Điều này sẽ làm gián đoạn quá trình của bạn (trừ khi bạn bắt đầu nó trong một chuỗi), nhưng bạn có thể sử dụng codemô-đun để khởi động bảng điều khiển Python:

import code
code.interact()

Điều này sẽ chặn cho đến khi người dùng thoát khỏi bảng điều khiển tương tác bằng cách thực thi exit().

Các codemô-đun có sẵn trong ít nhất Python v2.6, có lẽ những người khác.

Tôi có xu hướng sử dụng cách tiếp cận này kết hợp với các tín hiệu cho công việc Linux của mình (đối với Windows, xem bên dưới). Tôi nhấn mạnh điều này ở đầu các tập lệnh Python của mình:

import code
import signal
signal.signal(signal.SIGUSR2, lambda sig, frame: code.interact())

Và sau đó kích hoạt nó từ một vỏ với kill -SIGUSR2 <PID>, nơi <PID>là quá trình ID. Sau đó, quá trình sẽ dừng bất cứ điều gì nó đang làm và trình bày một bảng điều khiển:

Python 2.6.2 (r262:71600, Oct  9 2009, 17:53:52)
[GCC 3.4.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

Nói chung từ đó tôi sẽ tải thành phần phía máy chủ của trình gỡ lỗi từ xa như WinPDB tuyệt vời .

Windows không phải là hệ điều hành tương thích với POSIX và do đó không cung cấp các tín hiệu tương tự như Linux. Tuy nhiên, Python v2.2 trở lên hiển thị tín hiệu dành riêng cho WindowsSIGBREAK (được kích hoạt bằng cách nhấn CTRL+ Pause/Break). Điều này không ảnh hưởng đến hoạt động CTRL+ C( SIGINT) bình thường và vì vậy là một giải pháp thay thế tiện dụng.

Do đó, một phiên bản di động, nhưng hơi xấu, ở trên là:

import code
import signal
signal.signal(
        vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR2"),
        lambda sig, frame: code.interact()
        )

Ưu điểm của phương pháp này:

  • Không có mô-đun bên ngoài (tất cả nội dung Python tiêu chuẩn)
  • Chỉ tiêu tốn ít tài nguyên cho đến khi được kích hoạt (2 lần nhập)

Đây là mã tôi sử dụng trong môi trường sản xuất của mình, mã này sẽ tải phía máy chủ của WinPDB (nếu có) và quay lại để mở bảng điều khiển Python.

# Break into a Python console upon SIGUSR1 (Linux) or SIGBREAK (Windows:
# CTRL+Pause/Break).  To be included in all production code, just in case.
def debug_signal_handler(signal, frame):
    del signal
    del frame

    try:
        import rpdb2
        print
        print
        print "Starting embedded RPDB2 debugger. Password is 'foobar'"
        print
        print
        rpdb2.start_embedded_debugger("foobar", True, True)
        rpdb2.setbreak(depth=1)
        return
    except StandardError:
        pass

    try:
        import code
        code.interact()
    except StandardError as ex:
        print "%r, returning to normal program flow" % ex

import signal
try:
    signal.signal(
            vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR1"),
            debug_signal_handler
            )
except ValueError:
    # Typically: ValueError: signal only works in main thread
    pass

Bạn có thể cung cấp thêm chi tiết về cách bạn tải thành phần phía máy chủ của WinPDB khi bạn có bảng điều khiển Python không?
Christian Long

1
Tôi đã thêm mã sản xuất của mình vào câu trả lời, nhưng về cơ bản bạn chỉ cần nhập thông tin sau vào bảng điều khiển: '' import rpdb2; rpdb2.start_embedded_debugger ("foobar", True, True) '' và sau đó khởi chạy WinPDB GUI với mật khẩu "foobar" khi được nhắc
RobM

26

Sử dụng pyrasite-shell . Tôi không thể tin rằng nó hoạt động tốt như vậy, nhưng nó có. " Cho nó một pid, nhận một vỏ ".

$ sudo pip install pyrasite
$ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope # If YAMA activated, see below.
$ pyrasite-shell 16262
Pyrasite Shell 2.0
Connected to 'python my_script.py'
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.

>>> globals()
>>> print(db_session)
>>> run_some_local_function()
>>> some_existing_local_variable = 'new value'

Điều này khởi chạy trình bao python với quyền truy cập vào các biến global () và local () của quá trình python đang chạy đó và những điều tuyệt vời khác.

Chỉ thử nghiệm này cá nhân trên Ubuntu nhưng dường như cũng phục vụ cho OSX.

Phỏng theo câu trả lời này .

Lưu ý: Dòng tắt thuộc ptrace_scopetính chỉ cần thiết cho các hạt nhân / hệ thống đã được tích hợp sẵn CONFIG_SECURITY_YAMA. Cẩn thận với ptrace_scope trong các môi trường nhạy cảm vì nó có thể tạo ra một số lỗ hổng bảo mật nhất định. Xem chi tiết tại đây .


@Dirk Tôi tin rằng ptrace_scope là điều cần thiết để cho phép một quy trình theo dõi / tương tác với một quy trình không liên quan khác.
python1981

Rõ ràng đó chỉ là trên các hệ thống có YAMA. Đề xuất chỉnh sửa và xóa bình luận ban đầu của tôi. (Cái này cũng sẽ xuất hiện trong một thời gian.)
Dirk

Xem tại đây để sử dụng trong Docker: stackoverflow.com/questions/37072468/…
Michael Steinberg

5

Tại sao không chỉ sử dụng mô-đun pdb ? Nó cho phép bạn dừng một tập lệnh, kiểm tra các giá trị của phần tử và thực thi từng dòng mã. Và vì nó được xây dựng dựa trên trình thông dịch Python, nó cũng cung cấp các tính năng được cung cấp bởi trình thông dịch cổ điển. Để sử dụng nó, chỉ cần đặt 2 dòng này vào mã của bạn, nơi bạn muốn dừng lại và kiểm tra nó:

import pdb
pdb.set_trace()

3
bạn có biết cách khởi chạy nó cho một chuỗi threading.enumerate () nhất định không?
yucer

4

Một khả năng khác, mà không cần thêm nội dung vào tập lệnh python, được mô tả ở đây:

https://wiki.python.org/moin/DebuggingWithGdb

Thật không may, giải pháp này cũng yêu cầu một số suy nghĩ trước, ít nhất là trong phạm vi mà bạn cần sử dụng phiên bản python với các ký hiệu gỡ lỗi trong đó.


Đối với hầu hết các bản phân phối Linux, python được xây dựng với các biểu tượng gỡ lỗi, nhưng các biểu tượng gỡ lỗi nằm trong một gói khác. Gói ký hiệu gỡ lỗi có thể được cài đặt sau khi tập lệnh python của bạn đã bắt đầu.
W.Mann

1

Khi sử dụng PyCharm, tôi không kết nối được với quá trình trong Ubuntu. Cách khắc phục là tắt YAMA. Để biết thêm thông tin, hãy xem askubuntu

echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.