2010-01-29 45 views
2

我想知道Python是否与C有关的某些代码元素的执行顺序有类似的问题。Python执行次序

例如,我知道用C有次说,当它不能保证某些变量在另一个之前初始化。或者仅仅因为一行代码高于另一行代码,并不能保证它在所有代码之下执行。

对于Python它是一样的吗?就像我打开一个数据文件,读入数据,关闭文件,然后执行其他的操作,我知道文件在我关闭文件之后的行被执行之前关闭了吗?

我之所以这样问是因为我想在一个大的数据文件(1.6GB)的阅读和使用特定于我对数据做好了这条巨蟒模块。当我运行这个模块,我得到这个错误信息:

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列)中的数据的大小。 我想也许如果我关闭了我读取数据后立即打开的文件,这将有所帮助,但事实并非如此。这让我想到了代码行执行的顺序,因此我的问题。

谢谢

+8

我认为你需要更好地解释自己。在C中,给定'f(); g();','f()'保证在'g()'之前被评估。在'a = f()+ g();'中,评估顺序未在C中指定.Python保证从左到右的评估:http://docs.python.org/reference/expressions.html#evaluation-订单 – 2010-01-29 15:42:35

+2

'问题'你的意思是'规则',对吧? – KevinDTimm 2010-01-29 15:47:56

+0

是的,我知道我不是很好地解释自己,对不起,它来自于不完全理解这一切,但也试图:) Alok:是的,这基本上是我在想什么。我认为这也延续到文件可能关闭时的情况。我知道我可以说定义了两个不同的函数,并从第一个调用第二个(第二个,我的意思是下面的代码),所以在这个意义上,它也不一定按顺序完成。 kevin:是的,我的意思是规则。我想我只是使用了工作问题,因为它给我麻烦:) – Jamie 2010-01-29 16:45:44

回答

3

执行C肯定是连续的,对于实际的语句。甚至有规则定义sequence points,所以你可以知道个别表达式是如何评估的。

2

CPython本身是以这样的方式编写的:像你提到的任何效果都被最小化;代码总是执行从上到下编译过程中禁止文字评估,对象是GCed只要其引用计数击中0等

10

我能想到的唯一的事情可能有些人感到惊讶的是:

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

print test() 

输出:

False 

finally条款确实在最后执行,即使return语句之前他们。但是,这不是特定于Python的。

1

“如果我打开数据文件,在数据的读取,关闭文件,然后做其他的东西,我知道肯定后,我关闭正在执行的文件的文件是线之前关闭?”

已关闭是的。

从内存中释放。不。没有关于垃圾收集何时发生的保证。

此外,关闭文件没有提到你离开周围铺设连接到这些变量,你已经创建了所有其他变量和其他对象。

没有“操作顺序”问题。

我敢打赌,你有数据太多拷贝太多的全局变量。

0

如果数据由列和行的,为什么不使用内置的文件迭代器在同一时间去取行?

f = open('file.txt') 
first_line = f.next() 
2

cpython vm中的执行是非常线性的。我不认为你的问题与执行的顺序有关。

有一件事你应该小心使用Python而不是C:异常到处都可以提出异议,因此只因为你看到一个close()调用下面的相应open()通话并不意味着实际上达到了这一呼吁。在任何地方使用try/finally(或者在足够新的python中使用with语句)以确保打开的文件已关闭(并且可以释放显式释放的其他类型的资源)。

如果你的问题是内存使用,而不是其他类型的资源,调试它可能会更困难。内存不能在python中显式释放。 cpython vm(最有可能使用的)只要最后一次引用它就释放内存,但有时无法释放与具有__del__方法的对象一起在循环中捕获的内存。如果你有自己的方法,或者使用有它们的类,这可能是你问题的一部分。但是,如果没有看到更多的代码,您的实际问题(内存一个,而不是执行顺序)很难回答。这可能是显而易见的(或者可能至少有一些明显的方法来减少你需要的内存量)。

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) 

man 2 fork

叉()函数可能会失败,如果:

[ENOMEM]
             存储空间不足。

os.popen4最后调用open2.Popen4.__init__,必须fork以创建您尝试从中读取数据的子进程/写。这种潜在的调用失败,可能是由于资源枯竭。

您可能在其他地方使用的内存太多,导致fork尝试使用多于给予用户的RLIMIT_DATA或RLIMIT_RSS限制。根据Python memory profiler - Stack Overflow推荐,Heapy可以帮助您确定是否属于这种情况。