简体   繁体   English

Python 程序占用内存

[英]Python program eating up RAM

I wrote a small program to collect data over serial port using MinimalModbus.我写了一个小程序来使用 MinimalModbus 通过串口收集数据。 The data is dumped into a CSV file.数据被转储到一个 CSV 文件中。 I have read several posts on SO and other places.我已经阅读了关于 SO 和其他地方的几篇文章。 A few things mentioned are:提到的几件事是:

  1. Using lazy evaluation wherever possible (xrange instead of range)尽可能使用惰性求值(xrange 而不是 range)
  2. Deleting large unused objects删除未使用的大对象
  3. Use child processes and upon their death memory is released by OS使用子进程并在它们死亡时由操作系统释放内存

The script is on github here .该脚本是在github 这里 I also use a script to periodically upload these files to a server.我还使用脚本定期将这些文件上传到服务器。 Both these scripts are fairly trivial.这两个脚本都相当简单。 Also nothing else is running on the system, thus i feel that withing these two systems only memory hogging is taking place.系统上也没有其他东西在运行,因此我觉得这两个系统只会发生内存占用。 What would be the best way to tackle this issue.解决这个问题的最佳方法是什么。 I am not the most willing to adopt the subprocess route.我不是最愿意采用子流程路线。

Some more information:更多信息:

  1. Data collection is on Raspberry Pi (512 MB RAM)数据收集在 Raspberry Pi(512 MB RAM)上
  2. Python version: 2.7 Python版本:2.7
  3. It takes about 3-4 days for RAM to be completely used after which the RaspberryPi freezes RAM完全使用大约需要3-4天,然后RaspberryPi冻结

I followed this guide to find out top 20 programs which are eating up RAM.我按照指南找出了消耗 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

So the two Python processes are eating up some RAM, but that is very small when compared to overall RAM consumed.因此,这两个 Python 进程占用了一些 RAM,但与消耗的总 RAM 相比,这非常小。 The following is the output of the free command.以下是 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

The following is the output of the top command.以下是 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 

EDIT 2编辑 2

As suggested in the first answer, i decided to look into log files.正如第一个答案中所建议的,我决定查看日志文件。 I had a look at syslog and the following is the result of tail on it.我查看了 syslog,下面是 tail 的结果。

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

These messages are filling up the log files and are coming every second.这些消息正在填满日志文件,并且每秒都会出现。 The interesting part is that i am using Ethernet and not WiFi.有趣的部分是我使用的是以太网而不是 WiFi。

Thus, now it is unclear where the RAM has gone?因此,现在还不清楚 RAM 去了哪里?

Most of your RAM is free for applications, because it's used for the buffers and caching.大多数 RAM 可用于应用程序,因为它用于缓冲区和缓存。 Look at the "-/+ buffers/cache:" line to see the amount of RAM that is really used/free.查看“-/+ buffers/cache:”行以查看实际使用/空闲的 RAM 量。 An explanation can be found here .可以在此处找到解释。

To verify wether Python is leaking memory, monitor that python's RSS size (or %mem) over time.要验证 Python 是否正在泄漏内存,请随时间监视 Python 的 RSS 大小(或 %mem)。 Eg write a shell-script that is called from a cron job every couple of hours to append the output of your ps command chain and the output of the free command to a file.例如,编写一个每隔几个小时从 cron 作业调用的 shell 脚本,以将ps命令链的输出和free命令的输出附加到文件中。

If you find that the Python processes are leaking memory there are a couple of things you can do;如果您发现 Python 进程正在泄漏内存,您可以执行以下操作:

  • Modify your script to that it extis after 24 hours and use a eg a cron job to restart it (the easy way out.)修改您的脚本使其在 24 小时后退出,并使用例如 cron 作业重新启动它(最简单的方法)。
  • Take an in-depth look into Python itself and expecially into the extension modules you're using.深入了解 Python 本身,尤其是您正在使用的扩展模块。 Use the gc module to monitor and influence the memory usage.使用gc模块来监控和影响内存使用。 You can eg call gc.count() regularly to monitor the amount of objects marked for collection.例如,您可以定期调用gc.count()来监视标记为收集的对象的数量。 You can call gc.collect() explicitly and see if that reduces memory usage.您可以显式调用gc.collect()并查看是否可以减少内存使用。 You could also modify the collection threshhold.您还可以修改收集阈值。

If Python's RAM use doesn't increase over time, it could be another program of daemon.如果 Python 的 RAM 使用不随时间增加,则它可能是另一个守护程序程序。 The memory logging script that I mentioned above should tell you which one it is.我上面提到的内存记录脚本应该告诉你它是哪一个。

There could also be another reason that your computer freezes.您的计算机死机也可能是另一个原因。 Look at the Linux logfiles for clues.查看 Linux 日志文件以获取线索。

Edit: Since you have wpa_supplicant filling up the log file, you should check the state of the filesystem(s).编辑:由于您有wpa_supplicant填写日志文件,您应该检查文件系统的状态。 A full filesystem might cause the system to hang.完整的文件系统可能会导致系统挂起。 If you aren't using the wireless interface, disable it.如果您不使用无线接口,请将其禁用。

import gc
gc.collect()

worked for me.为我工作。 This is taken from Roland Smith's accepted answer, and I thought it is useful for future searchers to point it out as an answer.这是摘自 Roland Smith 接受的答案,我认为未来的搜索者指出它作为答案很有用。

Maybe too late, but I had same problem on a droplet ubuntu server.也许为时已晚,但我在 Droplet ubuntu 服务器上遇到了同样的问题。 Had a cron job running python script every 15 minutes.每 15 分钟有一个运行 python 脚本的 cron 作业。 Three days later I ran out of memory.三天后,我的记忆力耗尽了。 So I decided to kill the python every x minutes via cron beacause I didn't find the solution.所以我决定通过 cron 每 x 分钟杀死一次 python,因为我没有找到解决方案。

I used this:我用过这个:

pkill -f scriptName.py pkill -f 脚本名.py

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM