4

コードの特定の要素の実行順序に関して、Python に C と同様の問題があるかどうか疑問に思っていました。

たとえば、C では、ある変数が別の変数の前に初期化されることが保証されていない場合があることを知っています。または、あるコード行が別のコード行の上にあるという理由だけで、それがその下のすべての行より前に実装されるとは限りません。

Pythonでも同じですか?たとえば、データのファイルを開き、データを読み取り、ファイルを閉じてから、ファイルを閉じた後の行が実行される前に、ファイルが閉じられていることを確認できますか??

私が尋ねる理由は、データの大きなファイル (1.6GB) を読み込もうとしていて、データに対して行う作業に固有のこの python モジュールを使用しようとしているためです。このモジュールを実行すると、次のエラー メッセージが表示されます。

    File "/glast01/software/ScienceTools/ScienceTools-v9r15p2-SL4/sane/v3r18p1/python/GtApp.py", line 57, in run
    input, output = self.runWithOutput(print_command)
  File "/glast01/software/ScienceTools/ScienceTools-v9r15p2-SL4/sane/v3r18p1/python/GtApp.py", line 77, in runWithOutput
    return os.popen4(self.command(print_command))
  File "/Home/eud/jmcohen/.local/lib/python2.5/os.py", line 690, in popen4
    stdout, stdin = popen2.popen4(cmd, bufsize)
  File "/Home/eud/jmcohen/.local/lib/python2.5/popen2.py", line 199, in popen4
    inst = Popen4(cmd, bufsize)
  File "/Home/eud/jmcohen/.local/lib/python2.5/popen2.py", line 125, in __init__
    self.pid = os.fork()
OSError: [Errno 12] Cannot allocate memory
>>> 
Exception exceptions.AttributeError: AttributeError("Popen4 instance has no attribute 'pid'",) in <bound method Popen4.__del__ of <popen2.Popen4 instance at 0x9ee6fac>> ignored

読み込んだデータのサイズに関連していると思います(17608310行と22列あります)。データを読み込んだ直後に開いたファイルを閉じると、おそらくこれが役立つと思いましたが、そうではありませんでした。これにより、コード行が実行される順序について考えるようになったので、私の質問です。

ありがとう

4

7 に答える 7

12

一部の人々を驚かせるかもしれないと私が考えることができる唯一のことは次のとおりです。

def test():
    try:
        return True
    finally:
        return False

print test()

出力:

False

finallyreturn句は、文が前にある場合でも、実際には最後に実行されます。ただし、これは Python に固有のものではありません。

于 2010-01-29T15:49:24.000 に答える
3

実際のステートメントでは、C の実行は確かにシーケンシャルです。シーケンス ポイントを定義するルールもあるため、個々の式がどのように評価されるかを知ることができます。

于 2010-01-29T15:39:54.287 に答える
3

CPython自体は、あなたが言及したような影響が最小限に抑えられるように書かれています。コードはコンパイル中にリテラル評価を除いて常に上から下へ実行され、オブジェクトは refcount が 0 になるとすぐに GC されます。

于 2010-01-29T15:41:35.653 に答える
3

cpython vm での実行は非常に直線的です。あなたが抱えている問題は、実行順序と関係があるとは思いません。

C ではなく Python で注意する必要があることの 1 つ: 例外はどこでも発生する可能性があるためclose()、対応する呼び出しの下に呼び出しがあるからといってopen()、呼び出しが実際に到達したことを意味するわけではありません。try/finallyどこでも (または十分に新しい python のステートメント) を使用withして、開いているファイルが閉じられていることを確認します (および、明示的に解放できる他の種類のリソースが解放されます)。

問題が他の種類のリソースではなく、メモリの使用にある場合は、デバッグが難しくなる可能性があります。Python ではメモリを明示的に解放することはできません。cpython vm (使用している可能性が最も高い) は、最後の参照がなくなるとすぐにメモリを解放しますが、メソッドを持つオブジェクトのサイクルに閉じ込められたメモリを解放できない場合があります__del__。独自のメソッドがある場合__del__、またはそれらを持つクラスを使用している場合、これが問題の一部である可能性があります。

ただし、実際の質問 (実行順序ではなくメモリに関する質問) は、さらにコードを見ないと答えにくいです。それは明らかなことかもしれません (または、必要なメモリの量を減らすための明らかな方法が少なくともあるかもしれません)。

于 2010-01-29T19:16:55.267 に答える
1

「データのファイルを開いて、データを読み込んで、ファイルを閉じてから、ファイルを閉じた後の行が実行される前に、ファイルが閉じられていることを確認できますか?」

はい、閉店しました。

メモリから解放されました。いいえ。ガベージコレクションがいつ発生するかについての保証はありません。

さらに、ファイルを閉じると、作成した他のすべての変数や、それらの変数にアタッチされたままにしておいた他のオブジェクトについては何もわかりません。

「操作の順序」の問題はありません。

データのコピーが多すぎるグローバル変数が多すぎることは間違いありません。

于 2010-01-29T17:55:49.430 に答える
0

popen2.py

class Popen4(Popen3):
    childerr = None

    def __init__(self, cmd, bufsize=-1):
        _cleanup()
        self.cmd = cmd
        p2cread, p2cwrite = os.pipe()
        c2pread, c2pwrite = os.pipe()
        self.pid = os.fork()
        if self.pid == 0:
            # Child
            os.dup2(p2cread, 0)
            os.dup2(c2pwrite, 1)
            os.dup2(c2pwrite, 2)
            self._run_child(cmd)
        os.close(p2cread)
        self.tochild = os.fdopen(p2cwrite, 'w', bufsize)
        os.close(c2pwrite)
        self.fromchild = os.fdopen(c2pread, 'r', bufsize)

男2フォーク

fork()関数は、次の場合に失敗する可能性があります。

[ENOMEM]
        十分なストレージスペースが利用できません。

os.popen4最終的にはを呼び出します。これは、読み取り/書き込みを試みる子プロセスを作成するためにopen2.Popen4.__init__必要です。forkこの基になる呼び出しは、おそらくリソースの枯渇が原因で失敗しています。

他の場所でメモリを使いすぎて、ユーザーに指定されたRLIMIT_DATAまたはRLIMIT_RSSの制限をfork超えて使用しようとしている可能性があります。Pythonメモリプロファイラー(Stack Overflow )で推奨されているように、Heapyはこれが当てはまるかどうかを判断するのに役立ちます。

于 2010-01-29T19:55:57.827 に答える
0

データが列と行で構成されている場合は、組み込みのファイルイテレータを使用して一度に1行ずつフェッチしてみませんか?

f = open('file.txt')
first_line = f.next()
于 2010-01-29T17:58:50.220 に答える