を介してインストールするPythoneggとしてパッケージ化したコマンドラインアプリケーションでPLYを使用していますpip
。コマンドラインからスクリプトを実行するたびに、次のメッセージが表示されます。
"Generating LALR tables"
さらに、parser.outファイルとparsetab.pyファイルは、スクリプトが呼び出されたディレクトリに書き込まれます。これらのファイルをアプリケーションに同梱して、毎回テーブルが再生成されないようにする方法はありますか?
使用する
yacc.yacc(debug=0, write_tables=0)
lex を次のように呼び出して、optimized modeを使用したい:
lexer = lex.lex(optimize=1)
.
強調する価値があります(同じリンクから):
以降の実行では、lextab.py がインポートされてレクサーが構築されます。このアプローチにより、レクサーの起動時間が大幅に短縮され、Python の最適化モードで動作します。
最適化モードで実行する場合、lex はほとんどのエラー チェックを無効にすることに注意してください。したがって、これは、すべてが正しく機能していて、本番コードのリリースを開始する準備が整っている場合にのみ推奨されます。
これは製品コードであるため、これはまさにあなたが望むもののように聞こえます。
.
この問題を調べていると、さまざまな Yacc のメモに出くわしました。
LALR テーブルの生成には比較的コストがかかるため、以前に生成されたテーブルがキャッシュされ、可能であれば再利用されます。テーブルを再生成する決定は、すべての文法規則と優先順位規則の MD5 チェックサムを取得することによって決定されます。不一致が発生した場合にのみ、テーブルが再生成されます。
内のyacc
関数yacc.py
を詳しく調べると、次のスニペットで最適化がこの不一致を無視していることがわかります。
if optimize or (read_signature == signature):
try:
lr.bind_callables(pinfo.pdict)
parser = LRParser(lr,pinfo.error_func)
parse = parser.parse
return parser
ここで、 (as )signature
に格納されているチェックサムと比較されます。parsetab.py
_lr_signature
outputdir
これは古い質問ですが、生成されたパーサー テーブルをプロジェクト内の特定のディレクトリに配置するために yacc キーワード引数を使用しようとしたとき、ply で同様の問題に遭遇しました。時間問わず。github でこのパッチを見つけました。これにより、目立った悪影響はなく、再生の問題が解決されました。基本的にはread_table
、クラスのメソッドを変更しyacc
て追加のパラメーター (the outputdir
--) を取得し、再生成の前にそのディレクトリを検索するだけです。これを機能させるには、read_table
(メソッド内の) への唯一の呼び出しサイトも、キーワード引数yacc
を渡すように変更する必要があります。outputdir
私が最終的にやったのは、最適化をオフにすることでした。PLY 3.4 のソースを調べていたところ、レクサー コードに次の小さなナゲットが見つかりました。
# If in optimize mode, we write the lextab
if lextab and optimize:
lexobj.writetab(lextab,outputdir)
return lexobj
レクサーとパーサーを構築するコードを次のように変更します。
self.lexer = lex.lex(module=self, optimize=False, debug=False, **kwargs)
と
self.lexer = lex.lex(module=self, optimize=False, debug=False, **kwargs)
すべてのファイルの書き込みを回避しました。デバッガーは.out
ファイルをディレクトリに書き込み、Python ファイルはoptimize
フラグの結果です。
これは当分の間機能しますが、このアプローチに完全に満足しているとは言えません. おそらく、最適化を維持し、同時に作業ディレクトリをクリーンに保つ何らかの方法があれば、パフォーマンスが向上する優れたソリューションになるでしょう。他の誰かがより良い方法論を持っている場合、私はそれに対してオープンです。
どうやら、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):
したがって、別のエラーログとデバッグログを渡すだけです(stdout / stderrに出力されないdebug()などのメソッドを使用します)。そして、固定のoutputdirを指定します。そして、それはあなたがする必要があるすべてです。
更新:チェックしたところ、これは正しい設定です:
yacc.yacc(
debug=False, # do not create parser.out
outputdir=r"c:\temp\aaa" # instruct to place parsetab here
)
実際には、すでにparsetab.pyが含まれているoutputdirを使用する必要があります。これにより、メッセージだけでなく、プログラムがparsetab.pyを書き出すこともなくなります。使用するだけです。