2012-09-28 29 views
6

Tôi đang sử dụng PLY trong ứng dụng dòng lệnh mà tôi đóng gói dưới dạng trứng Python được cài đặt thông qua pip. Mỗi lần tôi chạy kịch bản của tôi từ dòng lệnh, tôi thấy thông báo sau:Cách ngăn tái tạo bảng trong PLY

"Generating LALR tables" 

Bên cạnh đó, parser.out và parsetab.py tập tin được ghi vào thư mục mà từ đó các kịch bản được gọi. Có cách nào để gửi các tệp này với ứng dụng sao cho nó không tạo lại các bảng mỗi lần?

+0

Tôi không biết liệu có thể thực hiện điều này bằng 'ply' hay không. Bạn có thể thay đổi tên tệp hoặc thư mục để sử dụng hoặc chọn luôn tạo lại các bảng (có thể không phải là một tùy chọn, tùy thuộc vào kích thước ngữ pháp của bạn). Nhưng để gửi bảng phân tích cú pháp được tạo ... không biết. :/ – elias

Trả lời

0

Điều cuối cùng tôi làm là tắt tối ưu hóa. Tôi đã đi qua nguồn LỚP 3.4 và tôi thấy nugget nhỏ này trong mã lexer:

# If in optimize mode, we write the lextab 
if lextab and optimize: 
    lexobj.writetab(lextab,outputdir) 

return lexobj 

Bằng cách thay đổi mã mà xây dựng lexer và phân tích cú pháp để:

self.lexer = lex.lex(module=self, optimize=False, debug=False, **kwargs)

self.lexer = lex.lex(module=self, optimize=False, debug=False, **kwargs)

Tôi tránh tất cả việc ghi tệp. Trình gỡ lỗi ghi các tệp .out vào thư mục và các tệp Python là kết quả của cờ optimize.

Trong khi điều này làm việc trong thời gian này, tôi không thể nói rằng tôi hoàn toàn hài lòng với cách tiếp cận này. Có lẽ, có một số cách để giữ cho tối ưu hóa trên và, cùng một lúc, giữ cho thư mục làm việc sạch sẽ là một giải pháp cao cấp sẽ dẫn đến hiệu suất tốt hơn. Nếu ai đó có phương pháp tốt hơn, tôi sẽ cởi mở hơn với nó.

-1

Rõ ràng, có lập luận cho điều này trong ply.yacc:

def yacc(method='LALR', debug=yaccdebug, module=None, tabmodule=tab_module, start=None, 
    check_recursion=1, optimize=0, write_tables=1, debugfile=debug_file,outputdir='', 
    debuglog=None, errorlog = None, picklefile=None): 

Vì vậy, bạn chỉ cần vượt qua một errorlog và debuglog khác (với debug() vv phương pháp mà không in ra stdout/stderr). Và bạn chỉ định một outputdir cố định. Và đó là tất cả những gì bạn cần làm.

UPDATE: Tôi chỉ cần kiểm tra và điều này là thiết lập chính xác:

yacc.yacc(
    debug=False,       # do not create parser.out 
    outputdir=r"c:\temp\aaa" # instruct to place parsetab here 
) 

Trên thực tế bạn cần phải sử dụng một outputdir rằng đã có chứa parsetab.py. Điều này sẽ loại bỏ không chỉ thông điệp mà chương trình của bạn sẽ không viết ra parsetab.py. Nó sẽ chỉ sử dụng nó.

+1

OP không yêu cầu đơn giản là không hiển thị thông báo, nhưng không phải tạo lại các tệp bảng phân tích cú pháp tạm thời mọi lúc. – elias

+0

Tôi đoán rằng khi bạn sử dụng một thư mục cố định và bạn đã đặt các tệp ở đó, chúng sẽ không được tạo lại. Nhưng tôi sẽ cố gắng và cho bạn biết kết quả. – nagylzs

+0

'debug = False' thực sự ngăn chặn thông báo lỗi, nhưng không ngăn chặn việc tạo tập tin. Khi tôi sử dụng nó cùng với vị trí triển khai (nơi các tập tin đã tồn tại) nó vẫn cố gắng ghi đè lên chúng. – Michael

2

Bạn muốn sử dụng optimized mode, bằng cách gọi lex như:

lexer = lex.lex(optimize=1) 

.

Đó là giá trị nhấn mạnh (from the same link):

On hành tiếp theo, lextab.py sẽ chỉ đơn giản là được nhập khẩu để xây dựng lexer. Cách tiếp cận này cải thiện đáng kể thời gian khởi động của lexer và nó hoạt động trong chế độ tối ưu của Python.

Khi chạy ở chế độ được tối ưu hóa, điều quan trọng cần lưu ý là lex vô hiệu hóa việc kiểm tra lỗi nhất. Vì vậy, đây thực sự là chỉ được khuyến nghị nếu bạn chắc chắn mọi thứ đang hoạt động chính xác và bạn đã sẵn sàng bắt đầu phát hành mã sản xuất.

Vì đây là mã sản xuất, điều này nghe có vẻ giống như những gì bạn muốn.

.

Trong xem xét vấn đề này, tôi đi qua các miscellaneous Yacc notes:

Kể từ khi thế hệ của các bảng LALR là tương đối đắt tiền, bảng được tạo ra trước đó được lưu trữ và tái sử dụng nếu có thể. Quyết định tái tạo các bảng được xác định bằng cách kiểm tra MD5 của tất cả các quy tắc ngữ pháp và các quy tắc ưu tiên. Chỉ trong trường hợp không phù hợp là các bảng được tái tạo.

Và nhìn sâu hơn vào yacc chức năng bên trong yacc.py, chúng ta thấy tối ưu hóa mà bỏ qua không phù hợp này trong đoạn mã sau:

if optimize or (read_signature == signature): 
    try: 
     lr.bind_callables(pinfo.pdict) 
     parser = LRParser(lr,pinfo.error_func) 
     parse = parser.parse 
     return parser 

nơi signature được so sánh với checksum lưu trữ trong parsetab.py (như _lr_signature).

+0

Có điều gì bạn cần làm ngoài việc thiết lập tối ưu = 1 trong trình phân tích cú pháp và lexer không? Khi tôi thực hiện điều đó, nó vẫn tái tạo các tệp và vẫn in ra thông báo – Michael

11

sử dụng

yacc.yacc(debug=0, write_tables=0) 
+0

Lưu ý: bạn thực sự nên sử dụng 'debug = False, write_tables = False' ''' chỉ xảy ra để làm việc nhưng rõ ràng hơn là sử dụng' True'/'False' và tài liệu cũng sử dụng' bool' và không phải là số nguyên. – Bakuriu

0

Đây là một câu hỏi cũ, nhưng tôi chạy vào một vấn đề tương tự với lớp khi tôi cố gắng sử dụng đối số từ khóa outputdir yacc để đặt các bảng phân tích cú pháp được tạo ra trong thư mục cụ thể trong dự án của tôi - - nó sẽ đặt chúng ở đó, nhưng tái tạo chúng mỗi lần bất kể. Tôi tìm thấy this bản vá trên github đã giải quyết được vấn đề tái tạo mà không có hiệu ứng đáng chú ý nào. Về cơ bản, tất cả những gì bạn làm là sửa đổi phương thức read_table trên lớp yacc để có thêm tham số - số outputdir - và tìm kiếm thư mục ở đó trước khi tạo lại. Để thực hiện công việc đó, trang web gọi duy nhất tới read_table (theo phương thức yacc) cũng cần được sửa đổi để chuyển đối số từ khóa outputdir.

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