Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用urrlib2时如何解决Python内存泄漏问题?_Python_Memory Leaks_Urllib2_S60_Pys60 - Fatal编程技术网

使用urrlib2时如何解决Python内存泄漏问题?

使用urrlib2时如何解决Python内存泄漏问题?,python,memory-leaks,urllib2,s60,pys60,Python,Memory Leaks,Urllib2,S60,Pys60,我正在尝试为我的手机编写一个简单的Python脚本,以便使用urrlib2定期加载网页。事实上,我并不真正关心服务器响应,我只想将URL中的一些值传递给PHP。问题在于,PythonforS60使用的是旧的2.5.4Python内核,该内核在urrlib2模块中似乎存在内存泄漏。正如我所读到的,在每种类型的网络通信中似乎都存在这样的问题。这个bug在几年前就被报道过,同时也发布了一些解决方法。在谷歌的帮助下,我已经尝试了在该页面上能找到的一切,但我的手机在加载了约70页后仍然内存不足。奇怪的是,

我正在尝试为我的手机编写一个简单的Python脚本,以便使用urrlib2定期加载网页。事实上,我并不真正关心服务器响应,我只想将URL中的一些值传递给PHP。问题在于,PythonforS60使用的是旧的2.5.4Python内核,该内核在urrlib2模块中似乎存在内存泄漏。正如我所读到的,在每种类型的网络通信中似乎都存在这样的问题。这个bug在几年前就被报道过,同时也发布了一些解决方法。在谷歌的帮助下,我已经尝试了在该页面上能找到的一切,但我的手机在加载了约70页后仍然内存不足。奇怪的是,Garbege收集者似乎也没有什么不同,只是让我的脚本慢了很多。据说,较新的(3.1)内核解决了这个问题,但不幸的是,我不能等待一年(或更长)的S60端口的到来

下面是我的脚本在添加我发现的每一个小技巧后的样子:

import urrlib2, httplib, gc
while(true):
 url = "http://something.com/foo.php?parameter=" + value 
 f = urllib2.urlopen(url)
 f.read(1)
 f.fp._sock.recv=None # hacky avoidance
 f.close()
 del f
 gc.collect()

导入urrlib2、httplib、gc
虽然(正确):
url=”http://something.com/foo.php?parameter=“+价值
f=urllib2.urlopen(url)
f、 读(1)
f、 fp._sock.recv=None#黑客规避
f、 关闭()
德尔夫
gc.collect()
有什么建议,如何让它永远工作而不出现“无法分配内存”错误? 谢谢你的预告, 干杯,b_m

更新: 在内存耗尽之前,我已经连接了92次,但仍然不够好

更新2: 如前所述尝试了套接字方法,这是迄今为止第二个最佳(错误)解决方案:


类UpdateSocketThread(threading.Thread):
def运行(自):
全球数据
而1:
url=“/foo.php?参数=%d”%data
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s、 连接(('something.com',80))
s、 发送('GET'+url+'HTTP/1.0\r\n\r\n')
s、 关闭()
睡眠(1)
我也试过一些小把戏。上传50次后线程关闭(手机还剩下50MB内存,显然Python外壳没有)

更新: 我想我离解决方案越来越近了!我尝试在不关闭和重新打开套接字的情况下发送多个数据。这可能是关键,因为此方法将只留下一个打开的文件描述符。问题是:


导入套接字
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
socket.connect(((“something.com”,80))
socket.send(“test”)#返回4(发送字节,这很酷)
socket.send(“test”)#4
socket.send(“test”)#4
socket.send(“GET/foo.php?parameter=bar HTTP/1.0\r\n\r\n”)#返回发送的字节数,确定吗
socket.send(“GET/foo.php?parameter=bar HTTP/1.0\r\n\r\n”)#在手机上返回0,在Windows7上返回错误*
socket.send(“GET/foo.php?parameter=bar HTTP/1.0\r\n\r\n”)#在手机上返回0,在Windows7上返回错误*
socket.send(“test”)#返回0,奇怪。。。
*:错误消息:10053,软件导致连接中止

为什么我不能发送多条消息???

这似乎是一个(非常!)黑客的解决方法,但在这个问题上有点谷歌搜索:

显然,添加
f.read(1)
将阻止泄漏

import urllib2
f = urllib2.urlopen('http://www.google.com')
f.read(1)
f.close()

编辑:哦,我看你已经有了
f.read(1)
。。。我已经没有主意了:/

考虑使用低级别(相关)而不是urllib2

HOST = 'daring.cwi.nl'    # The remote host
PORT = 50007              # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.send('GET /path/to/file/index.html HTTP/1.0\n\n')

 # you'll need to figure out how much data to read and read that exactly
 # or wait for read() to return data of zero length (I think!)
DATA_SZ = 1024
data    = s.recv(DATA_SZ)
s.close()
print 'Received', repr(data)
如何通过低级套接字执行和读取HTTP请求有点超出了问题的范围(可能会在stackoverflow上提出一个很好的问题-我搜索了,但没有看到),但我希望这将为您指明解决问题的解决方案的方向


在这里编辑一个关于使用
makefile
的答案可能会有所帮助:

使用您链接建议的测试代码,我测试了Python安装,并确认它确实泄漏了。但是,如果像@Russell建议的那样,我将每个
urlopen
放在自己的进程中,操作系统应该清理内存泄漏。在我的测试中,内存、无法访问的对象和打开的文件都或多或少保持不变。我将代码拆分为两个文件:

连接.py
显然,这是顺序性的,因此一次只能执行一个连接,这可能是您的问题,也可能不是。如果是的话,您必须找到一种非阻塞的方式来与正在启动的进程进行通信,但我将把它作为一种练习留给您


编辑:重读您的问题时,您似乎不关心服务器的响应。在这种情况下,您可以删除所有与酸洗相关的代码。显然,您的最终代码中也不会有与
print\u unreachable\u len()
相关的位。

对于我来说,在Mac上的Python 2.6.1不会泄露这一点。您使用的是哪个版本

顺便说一句,你的程序不工作,由于一些打字错误。以下是一个有效的方法:

import urllib2, httplib, gc
value = "foo"
count = 0
while(True):
    url = "http://192.168.1.1/?parameter=" + value 
    f = urllib2.urlopen(url)
    f.read(1)
    f.fp._sock.recv=None # hacky avoidance
    f.close()
    del f
    print "count=",count
    count += 1

根据平台和python版本的不同,python可能不会将内存释放回操作系统。看这个。也就是说,python不应该无休止地消耗内存。从您使用的代码判断,它似乎是python运行时中的bug,除非urllib/sockets使用globals,我不相信它会使用globals-将其归咎于S60上的python


您是否考虑过其他内存泄漏源?无休止的日志文件打开,不断增加的数组或smth之类的?如果它确实是套接字接口中的一个bug,那么您唯一的选择就是使用子进程方法。

我认为这可能是您的问题。总而言之,Pys60的DNS查找中存在内存泄漏,您可以通过将DNS查找移到内部循环之外来解决此问题。

在urllib2.py:1216中创建的urllib2中存在一个引用循环。该问题自2009年以来一直存在。

我不熟悉执行环境,但是否可以每次将负载作为单独的进程生成,并让操作系统进程清理来处理泄漏?这可能是一个好主意,谢谢,我会给它一个tr
HOST = 'daring.cwi.nl'    # The remote host
PORT = 50007              # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.send('GET /path/to/file/index.html HTTP/1.0\n\n')

 # you'll need to figure out how much data to read and read that exactly
 # or wait for read() to return data of zero length (I think!)
DATA_SZ = 1024
data    = s.recv(DATA_SZ)
s.close()
print 'Received', repr(data)
import cPickle, urllib2

def connectFunction(queryString):
    conn = urllib2.urlopen('http://something.com/foo.php?parameter='+str(queryString))
    data = conn.read()
    outfile = ('sometempfile'. 'wb')
    cPickle.dump(data, outfile)
    outfile.close()

if __name__ == '__main__':
    connectFunction(sys.argv[1])
###launcher.py
import subprocess, cPickle

#code from your link to check the number of unreachable objects

def print_unreachable_len():
    # check memory on memory leaks
    import gc
    gc.set_debug(gc.DEBUG_SAVEALL)
    gc.collect()
    unreachableL = []

    for it in gc.garbage:
        unreachableL.append(it)
    return len(str(unreachableL))

    #my code
    if __name__ == '__main__':        
        print 'Before running a single process:', print_unreachable_len()
        return_value_list = []
        for i, value in enumerate(values): #where values is a list or a generator containing (or yielding) the parameters to pass to the URL
             subprocess.call(['python', 'connection.py', str(value)])
             print 'after running', i, 'processes:', print_unreachable_len()
             infile = open('sometempfile', 'rb')
             return_value_list.append(cPickle.load(infile))
             infile.close()
import urllib2, httplib, gc
value = "foo"
count = 0
while(True):
    url = "http://192.168.1.1/?parameter=" + value 
    f = urllib2.urlopen(url)
    f.read(1)
    f.fp._sock.recv=None # hacky avoidance
    f.close()
    del f
    print "count=",count
    count += 1