辞書内包内のSearchCursorで使用されるカーソルを削除しますか?


12

withステートメントを使用してカーソルを開き、削除されていることを確認するのが最善の場合は、次のようにします。

with arcpy.da.UpdateCursor(fc,fields) as cursor:

次に、カーソルが次のような内包表記で反復可能オブジェクトとして使用される場合:

d = {k:v for (k,v) in arcpy.da.SearchCursor(fc,fields)}

理解に使用した後、カーソルを削除する必要がありますか?


1
いい質問ですね。スキーマロックを処理しようとしていますか?新しいdaカーソルに関する明確なソースを見つけることができませんが、同様のトピックに関するいくつかの初期の(ほとんど時代遅れの)投稿があります:sgillies.net/2011/02/01/get-with-it.htmlおよびhelp.arcgis.com/ ja / arcgisdesktop / 10.0 / help / index.html#//…。特に、最初のリンクの下部にある@JasonScheirerのコメントを見てください。
アーロン

回答:


13

絶対に必要かどうかは、尋ねるのが間違っている質問です。問題は、それが良いアイデアかどうかです。

プログラミングのルールとして、あなたは奇妙なことをすることを避け、仕事に最適なツールを使用する必要があります。何かにリソースを解放する明示的な方法がある場合は、リリースを明示的に行い、それで完了します。

with arcpy.da.UpdateCursor(fc,fields) as cursor:
    d = {k: v for (k,v) in cursor}

気づかないかもしれませんが、このwith句は実際に追加のロジックを呼び出します。with句は有していなければならないコンテキストマネージャ、必要__enter__(ブロックが入力されたときに呼び出さ)と__exit__(ブロックが終了されたときに呼び出される)方法を。特に、__exit__例外が発生したかどうかに関係なくメソッドが呼び出されるため、プログラムはエラーが発生しても常にリソースを解放します。これにより、リソースがいつ取得され、いつ解放されるかをコードに明示的に示すことができ、リソースをできるだけ早く解放できるようになります。

対照的に、実際にランタイムに依存して魔法のようにすぐに閉じることはできません。これは、オブジェクトを閉じる方法がオブジェクトのデストラクタを呼び出すことであるためです。Pythonは、デストラクタがいつ呼び出されるかについては保証しませんが、オブジェクトがガベージコレクションされるときに最終的に保証されるだけです。(こちらを参照してください。)現在、Pythonは実装されているため、オブジェクトへの参照がなくなるとすぐにPythonが実行されます。しかし、誤ってオブジェクトへの参照を伝播するのは簡単であり、Pythonのランタイムが変更される可能性があります。

長期的なメンテナンスも考慮してください。現在、長期的な参照ありません、参照あるようにコードを変更する必要がある場合、6か月で何が起こりますか?他の誰かがそれをした場合はどうなりますか?変更を行う人は、withブロックがまだ存在しないため、ブロックに切り替えるとは思わないかもしれません。リソースをクリーンアップすることを習慣にすると、問題をはるかに少なくすることができます。

ガベージコレクションの実装の詳細にコードを本当に関連付けたいですか?例外を介して誤って参照を伝播している可能性があるかどうかを常に考えなければなりませんか?いいえ、そうではありません。スクリプトがArcMapで呼び出されたときにそれが起こった場合を想像してください。ユーザーは、ファイルを解放するためだけにプロセス全体を閉じることを強制されます。ですから、そのような立場に置かないでください。リソースを明示的に解放します。1行のコードを保存しても、それが引き起こす問題のリスクに見合う価値はありません。コンテキストマネージャーは、Pythonでリソースを取得および解放するための標準メカニズムであり、非常にうまく機能します。

結論としては、明示的にリリースしないことは悪い考えです。

もちろん、これは、コードが他の誰かに影響を与える可能性があることを前提としています。他の誰かが実行または保守する必要があるスクリプトにコードを入れるなど、変更を保存できません。あなたが問題の影響を受けるのはあなただけであるならば、どうしても、あなたが望むすべての良い慣行に直面して飛びましょう。


3

いいえ、cursor理解してから使用した後に削除する必要はありません。A cursorはオブジェクトのクラスのインスタンスです(Pythonのすべてはオブジェクトです)。すべてのpythonセッションには、セッションnamespace内のすべてのオブジェクトへの参照を含むがあります。キーは各オブジェクトへの参照であり、値はオブジェクトそのものである辞書のように考えてください。「参照カウント」-そのオブジェクトを参照するキーの数-がゼロになると、オブジェクトが削除され、メモリが再割り当てされます。cursor内包表記でa を使用する場合、名前空間にはそのオブジェクトへの参照はありません。理解が完了すると、オブジェクトは削除されます。

名前空間にはエントリがないため、何も削除する必要はありません。ESRIは、例2のこの構文も示しています。

さらに明確にするために、実行する場合:

>>> import arcpy
>>> f = r'C:\Workspace\study_area.shp'
>>> a = arcpy.da.SearchCursor(f, ['*'])

ディレクトリに.lockファイルが表示されます(ファイルエクスプローラーを確認してください)。カーソルへの参照はでa、削除さcursorれるまで(したがって、ロックが)持続しaます。したがって、次に実行すると:

>>> del(a)

名前空間のエントリが削除され、ロックが解除されます(.lockファイルは消えます)。実行する場合:

>>> t = [i for i in arcpy.da.SearchCursor(f, ['*'])]

ロックファイルが表示されないか、コマンドが完了すると表示されなくなります。名前空間にエントリcursorがないと、永続的ではありません。t作成したリストではなく、作成したリストを参照しますcursor

要約するcursorsと、名前空間に参照がある場合(つまりa、上記の例のように変数に変数を割り当てた場合)に削除することだけを心配する必要があります。


2
これは非常に貧弱なプログラミング手法です。リソースを解放する明示的な方法がある場合は、それを使用します。
jpmc26

@ jpmc26、どの部分が「非常に貧弱なプログラミング慣行」ですか?一般的な理解?または、イテラブルが理解内でインスタンス化されている場合のみ?後者の1つの強力な議論は、リソースをすぐに解放することだと思いました。
トム

@Tomリソースを明示的に解放しません。理解は素晴らしいツールであり、その内部で通常のイテラブルをインスタンス化することは完全に普通です。ここで悪いのは、カーソルオブジェクトがファイルロックを取得し、それらの明示的なリリースがないことです。詳細については私の答えをご覧ください。
jpmc26

2

そのデータセットに排他ロックが存在する場合、テーブルまたはフィーチャクラスに対して更新および挿入カーソルを作成できません。データセットの排他ロックのため、UpdateCursorまたはInsertCursor関数は失敗します。これらの関数がカーソルを正常に作成すると、データセットに排他ロックを適用し、2つのスクリプトが同じデータセットに更新カーソルまたは挿入カーソルを作成できないようにします。

Pythonでは、カーソルが解放されるまでロックが持続します。そうしないと、他のすべてのアプリケーションまたはスクリプトが不必要にデータセットにアクセスできなくなる可能性があります。カーソルは、次のいずれかによって解放できます。

withステートメント内にカーソルを含めると、カーソルが正常に完了したかどうかに関係なく、ロックの解放が保証されます。

カーソルでreset()を呼び出します。

カーソルの完了。

Pythonのdelステートメントを使用してカーソルを明示的に削除する-ESRI

arcpy.daカーソルを使用したロックは、元のarcpyカーソルを使用したロックとほとんど同じです。

コードをテストした後、gberardが指摘したように、理解の終了後はカーソルへの参照はありません。
また、理解の終了後、フィーチャクラスにロックはありません。


1
何を削除しますか?理解の終了後、カーソルオブジェクトへの参照はないので、理論的には閉じられるはずです。ESRIの実装が期待どおりに動作するかどうかは別の質問であり、ドキュメントがそれを本当に答えているとは思いません。
マイクワット
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.