2012-01-02 33 views
7

Trong mô-đun tôi viết, tôi có (cho các giai đoạn phát triển và thử nghiệm) rất nhiều Print["Messages"]. Tôi có hai câu hỏi:Tạo thư trong mathematica

  1. Thực tiễn tốt nhất để in thông báo "gỡ lỗi" này là gì?
  2. Có cách nào để gọi mô-đun sao cho các tin nhắn sẽ được in KHÔNG? Ví dụ, khi gọi mô-đun từ mô-đun khác, tôi không muốn xem tất cả đầu ra của mô-đun đầu tiên.
+2

Trong v.8, cũng có 'Assert' tương tự ở chỗ nó in thông điệp về kiểm tra thất bại, và có thể được tắt –

+0

@ Verbeia Vâng, đúng vậy ... Tôi chỉ nghĩ rằng hai câu hỏi rất gần nhau sẽ có lợi khi họ sáp nhập và có tất cả câu trả lời ở cùng một nơi. Cho dù đó là một trong những sáp nhập vào này hoặc ngược lại nó không quan trọng ... – Szabolcs

+0

@ Szabolcs thấy tin nhắn cho bạn trong trò chuyện – Verbeia

Trả lời

12

Tôi thích để luôn luôn giữ các biến toàn cầu bắt đầu bằng các $, và các chức năng mà không có tiền tố, vì vậy tôi muốn viết:

debugPrint[args___] := $debugPrintFunction[args] 

$debugPrintFunction = Print[##] & 

Sau đó, bạn chỉ có thể sử dụng debugPrint chính xác như bạn muốn sử dụng Print hiện nay. Khi bạn muốn thoát khỏi những thông điệp gỡ lỗi, bạn chỉ cần bỏ đặt biến:

$debugPrintFunction = . 

Có một số lợi thế để làm nó theo cách này. Một là bạn có thể sử dụng Block để chuyển đổi các gỡ lỗi và tắt địa phương:

In[1]:= foo[x_] := (debugPrint[x]; x+1) 

In[2]:= foo[3] 
3 
Out[2]= 4 

In[3]:= Block[{$debugPrintFunction}, foo[3] 
Out[3]= 4 

Bạn thậm chí có thể tại địa phương thực hiện $debugPrintFunction làm cái gì khác, như Sow giá trị cho một Reap nhặt, hoặc trực tiếp các thông điệp debugging ở một nơi khác, như

strm = OpenWrite["your/log/path/here", InputForm]; 
Block[{$debugPrintFunction = Write[strm, ##]}, 
    foo[3]]; 
Close[strm]; 

được sử dụng một cách sáng suốt, các Phạm vi năng động cung cấp bởi Block cho phép việc sử dụng các biến toàn cục trong một cách tương đối an toàn và kiểm soát.

+0

Tôi đã hết phiếu, nhưng tôi sẽ upvote ngay sau khi túi được bổ sung –

+0

Điều đó thật tuyệt vời, cảm ơn bạn rất nhiều –

8

Mã cũ hơn của tôi sử dụng phương pháp như Pillsy mô tả.

Gần đây tôi đã sử dụng một cái đầu mà thường không có bất kỳ quy tắc, như:

... 
debugPrint[expr] 
... 

và sau đó có một chức năng thứ hai:

Attributes[PrintDebug]={HoldAll} 

PrintDebug[expr_] := Block[{debugPrint = Print}, expr] 

Sau đó, khi tôi muốn xem đầu ra gỡ lỗi Tôi có thể bọc PrintDebug quanh đầu vào:

PrintDebug[MyFunction[1,2,3]] 

hoặc, thường xuyên hơn là

MyFunction[1,2,3] // PrintDebug 

vì tôi tìm thấy dạng hậu tố dễ dàng thêm/xóa và tốt hơn để tập trung vào chức năng chính.

0

Đối với tôi, vì M không có trình gỡ rối tích hợp để nói, tôi lãng phí 50% thời gian của tôi chỉ trong gỡ lỗi, có thể đã được lưu nếu có trình gỡ lỗi. 50% mã phát triển của tôi là báo cáo In, vì không có các báo cáo này, tôi sẽ bị mất khi tìm thấy lỗi xuất phát từ đâu. (điều này cũng tồi tệ, vì quá nhiều thông điệp in trong mã, làm cho khó có thể xem thuật toán đôi khi, nó bị cản trở, nhưng không thể xóa nó, vì tôi có thể cần nó sau này).

Tôi thấy thật tuyệt vời khi một công cụ tính toán mạnh mẽ và linh hoạt như M, vẫn có môi trường phát triển tương đối kém hơn. Khi tôi đang sử dụng Matlab, tôi mất vài giây để tìm lỗi ở đâu, sử dụng trình gỡ rối.

Ai đó có thể nói sử dụng Bàn làm việc để gỡ lỗi. Tôi đã cố gắng sử dụng để gỡ lỗi một bản demo Manipulate, và tôi không thể tìm ra nó. Quá phức tạp để sử dụng. M cần một trình xây dựng trình gỡ rối đơn giản dễ sử dụng (trong chính sổ ghi chép, không phải là một chương trình riêng), và với các số dòng!

Ok, Với việc giới thiệu ở trên :), đây là những gì tôi làm bản thân mình để đáp lại câu hỏi của bạn:

  1. có mức độ khác nhau của các thông điệp debug. mức độ thô và mức chi tiết. Mức độ thô chỉ in một thông báo khi nó vào một hàm và khi nó tồn tại chức năng.

  2. Tôi có một nút trên giao diện người dùng để sử dụng để bật/tắt gỡ lỗi (nếu bạn đang làm chương trình dựa trên giao diện người dùng, nếu không nó sẽ có trong mã).

  3. Sử dụng chức năng gỡ lỗi riêng biệt, nơi thông báo gỡ lỗi đi qua trước khi được in. Trong đó, bạn có thể thêm dấu thời gian cho mỗi thư và như vậy trước khi in (cũng có thể kiểm soát nếu bạn muốn thư đi tới tệp văn bản, từ một nơi). Phần còn lại của mã của bạn, chỉ cần gọi hàm gỡ lỗi này với thông báo cần in. Tôi in tất cả mọi thứ ngay bây giờ để bàn giao tiếp, không cho máy tính xách tay hiện tại.

  4. Mỗi thông báo gỡ lỗi có tên hàm gọi lúc bắt đầu.

  5. Nếu bạn muốn kiểm soát gỡ lỗi ở cấp mô-đun, điều tôi làm, chỉ cần tạo cờ gỡ lỗi cục bộ bên trong Mô-đun và bật/tắt mỗi lần tôi muốn gỡ lỗi mô-đun cụ thể đó. Cờ gỡ lỗi cục bộ này đảm nhận cài đặt cờ gỡ lỗi toàn cục. Bằng cách này, tôi có thể gỡ lỗi chỉ một mô-đun nếu tôi muốn, và không phải phần còn lại của mã.

Có nhiều cách khác để tùy chỉnh tất cả điều này. Nhưng tôi thấy rằng nếu tôi dành nhiều thời gian sớm hơn để tạo ra một hệ thống thông báo gỡ lỗi tốt, nó sẽ giúp phân bổ lỗi khi cần.

Dưới đây là một số liên kết hữu ích

http://reference.wolfram.com/mathematica/guide/TuningAndDebugging.html

workbench debugger (nếu bạn có thể tìm cách sử dụng để gỡ lỗi thao tác và Dynamics, xin vui lòng cho tôi biết)

http://www.wolfram.com/products/workbench/features/debug.html

+3

Chỉ cần làm rõ, Mathematica * không * có một trình gỡ lỗi tích hợp, nơi bạn có thể thiết lập breakpoint, bước vào mã, vv Mặc dù nó là một chút bất tiện để sử dụng, nó là có. 'Đánh giá -> Debugger' – Szabolcs

+0

@ Szabolcs, vâng, tôi biết về điều đó. Nhưng nó thực sự có thể sử dụng được? Tôi chi tiêu có thể là 2 giờ vào nó ngày hôm kia, và thậm chí không thể tìm cách sử dụng nó ở tất cả để gỡ lỗi Manipulate máy tính xách tay của tôi. Cuối cùng, tôi đã từ bỏ, và quay lại để in tin nhắn :) – Nasser

+2

Nhiều người có thể bắt gặp câu hỏi và câu trả lời này, và tôi nghĩ rằng đó là gây hiểu lầm cho họ để nói rằng không có trình gỡ lỗi. Đúng là tôi không sử dụng nó nhiều, và nó không thực sự khủng khiếp, nhưng thỉnh thoảng tôi sử dụng nó. – Szabolcs

3

Tuy nhiên, một khả năng:

debugPrint::msg = "Debug message: `1`";  
debugPrint[msg_] := Message[debugPrint::msg, msg] 

Sử dụng các chức năng như thế này:

debugPrint["hello"] 

Tắt hoặc trên các thông điệp như thế này:

Off[debugPrint::msg] 

On[debugPrint::msg] 
6

Tôi thường cài đặt một tùy chọn verbosing vào chức năng của tôi, có thể được bật/tắt nếu cần thiết để gỡ lỗi. Lưu ý rằng bằng cách chỉ định mặc định cho Verbose bên trong hàm, bạn có thể kiểm soát xem thông tin có được in hay không.

In[5]:= func1[arg_, opts___] := Module[{verbose}, 
    verbose = Verbose /. {opts} /. {Verbose -> True}; 
    If[verbose, Print["Verbosing function1: arg is ", arg]]; 
    arg 
    ]; 

func2[arg_, opts___] := Module[{verbose}, 
    verbose = Verbose /. {opts} /. {Verbose -> False}; 
    func1[arg, Verbose -> verbose] 
    ]; 

In[7]:= func1[123] 

During evaluation of In[7]:= Verbosing function1: arg is 123 

Out[7]= 123 

In[8]:= func2[456] 

Out[8]= 456 

In[9]:= func1[123, Verbose -> False] 

Out[9]= 123 

In[10]:= func2[456, Verbose -> True] 

During evaluation of In[10]:= Verbosing function1: arg is 456 

Out[10]= 456 

Tất nhiên người ta có thể xây dựng ví dụ này là phù hợp với các tiêu chuẩn lập trình Mathematica (ví dụ thêm Options[func1, Verbose -> ...] header và sau đó truy cập vào Options từ bên trong hàm, nhưng đây không phải là điểm ở đây.

+1

Bạn có thể tìm thấy cũng hữu ích sau đây __verbose contr & in ["Verbosing function1: arg là", arg] __ thay vì IF. –

+0

Đó là một phím tắt thông minh, tiết kiệm cho tôi rất nhiều khung phù hợp, cảm ơn! –