Python程序占用RAM

时间:2013-05-19 08:06:08

标签: python linux memory-management garbage-collection raspberry-pi

我写了一个小程序,使用MinimalModbus通过串口收集数据。数据被转储到CSV文件中。我在SO和其他地方看过几篇帖子。提到的一些事情是:

  1. 尽可能使用延迟评估(xrange而不是范围)
  2. 删除大量未使用的对象
  3. 使用子进程并在其死亡记忆由OS发布
  4. 该脚本位于github here上。我还使用script定期将这些文件上传到服务器。 这两个脚本都相当简单。系统上也没有其他任何东西在运行,因此我觉得在这两个系统中只有内存占用正在进行。 什么是解决这个问题的最佳方法。我不是最愿意采用子进程路由。

    更多信息:

    1. 数据收集在Raspberry Pi(512 MB RAM)
    2. Python版本:2.7
    3. 完全使用RAM大约需要3-4天,之后RaspberryPi冻结
    4. 我按照this指南查找了占用RAM的前20个程序。

      $ ps aux | awk '{print $2, $4, $11}' | sort -k2rn | head -n 20
      12434 2.2 python
      12338 1.2 python
      2578 0.8 /usr/sbin/console-kit-daemon
      30259 0.7 sshd:
      30283 0.7 -bash
      1772 0.6 /usr/sbin/rsyslogd
      2645 0.6 /usr/lib/policykit-1/polkitd
      2146 0.5 dhclient
      1911 0.4 /usr/sbin/ntpd
      12337 0.3 sudo
      12433 0.3 sudo
      1981 0.3 sudo
      30280 0.3 sshd:
      154 0.2 udevd
      16994 0.2 /usr/sbin/sshd
      17006 0.2 ps
      1875 0.2 /usr/bin/dbus-daemon
      278 0.2 udevd
      290 0.2 udevd
      1 0.1 init
      

      因此,两个Python进程占用了一些RAM,但与消耗的整体RAM相比,这个数据非常少。以下是free命令的输出。

      pi@raspberrypi ~ $ free -m
                   total       used       free     shared    buffers     cached
      Mem:           438        414         23          0         45        320
      -/+ buffers/cache:         48        389
      Swap:           99          0         99
      

      以下是top命令的输出。

      Tasks:  69 total,   1 running,  68 sleeping,   0 stopped,   0 zombie
      %Cpu(s): 66.9 us,  5.0 sy,  0.0 ni, 18.1 id,  0.0 wa,  0.0 hi, 10.0 si,  0.0 st
      KiB Mem:    448776 total,   429160 used,    19616 free,    47016 buffers
      KiB Swap:   102396 total,        0 used,   102396 free,   332288 cached
      
      PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND           
      12338 root    20   0 10156 5644 2384 S  69.8  1.3   3059:31 python            
      26039 root    20   0     0    0    0 S   1.6  0.0   0:02.71 kworker/0:1       
      26863 pi      20   0  4664 1356 1028 R   1.3  0.3   0:00.12 top               
      1982 root     20   0  1752  516  448 S   0.3  0.1   1:08.36 sh                
      1985 root     20   0  1692  552  460 S   0.3  0.1   5:15.16 startpar          
      1 root        20   0  2144  728  620 S   0.0  0.2   0:17.43 init              
      2 root        20   0     0    0    0 S   0.0  0.0   0:00.14 kthreadd          
      3 root        20   0     0    0    0 S   0.0  0.0   0:13.20 ksoftirqd/0       
      5 root         0 -20     0    0    0 S   0.0  0.0   0:00.00 kworker/0:0H      
      7 root         0 -20     0    0    0 S   0.0  0.0   0:00.00 kworker/u:0H      
      8 root         0 -20     0    0    0 S   0.0  0.0   0:00.00 khelper           
      9 root        20   0     0    0    0 S   0.0  0.0   0:00.00 kdevtmpfs         
      10 root       0 -20     0    0    0 S   0.0  0.0   0:00.00 netns             
      12 root      20   0     0    0    0 S   0.0  0.0   0:00.06 bdi-default       
      13 root       0 -20     0    0    0 S   0.0  0.0   0:00.00 kblockd 
      

      编辑2

      正如第一个答案中所建议的那样,我决定查看日志文件。我查看了syslog,以下是尾部的结果。

      May 19 10:03:26 raspberrypi wpa_supplicant[7065]: wlan0: Failed to initialize driver    interface
      May 19 10:03:49 raspberrypi wpa_supplicant[7157]: nl80211: 'nl80211' generic netlink not found
      May 19 10:03:49 raspberrypi wpa_supplicant[7157]: Failed to initialize driver 'nl80211'
      May 19 10:03:49 raspberrypi wpa_supplicant[7157]: rfkill: Cannot open RFKILL control device
      May 19 10:03:49 raspberrypi wpa_supplicant[7157]: Could not read interface wlan0 flags: No such device
      

      这些消息正在填满日志文件并且每秒都会出现。有趣的是我使用以太网而不是WiFi。

      因此,现在还不清楚RA​​M的去向了什么?

3 个答案:

答案 0 :(得分:5)

大多数RAM对应用程序都是免费的,因为它用于缓冲区和缓存。查看“ - / + buffers / cache:”行以查看真正使用/免费的RAM量。可以找到解释here

要验证Python是否正在泄漏内存,请随着时间的推移监视python的RSS大小(或%mem)。例如。编写一个shell脚本,每隔几个小时从一个cron作业调用,将ps命令链的输出和free命令的输出附加到文件中。

如果您发现Python进程 泄漏内存,您可以执行以下操作;

  • 在24小时后将您的脚本修改为extis并使用例如重启它的一个cron作业(简单的出路。)
  • 深入了解Python本身,特别是您正在使用的扩展模块。使用gc模块监视并影响内存使用情况。你可以,例如定期致电gc.count()以监控标记为收集的对象数量。您可以显式调用gc.collect(),看看是否会减少内存使用量。您也可以修改集合阈值。

如果Python的RAM使用不会随着时间的推移而增加,那么它可能是守护进程的另一个程序。我上面提到的内存日志记录脚本应该告诉你它是哪一个。

还有另一个原因导致您的计算机死机。查看Linux日志文件以获取线索。

编辑:由于您wpa_supplicant填写了日志文件,因此您应该检查文件系统的状态。完整的文件系统可能会导致系统挂起。如果您不使用无线接口,请将其禁用。

答案 1 :(得分:0)

import gc
gc.collect()

为我工作。这取自罗兰史密斯接受的答案,我认为未来的搜索者将其作为答案指出是有用的。

答案 2 :(得分:0)

也许为时已晚,但是我在Dropout ubuntu服务器上遇到了同样的问题。每15分钟执行一次运行python脚本的cron作业。三天后,我内存不足。所以我决定每隔x分钟通过cron杀死python,因为我没有找到解决方法。

我用了这个:

pkill -f scriptName.py