J'essaie d'écrire un script Python simple pour mon téléphone portable pour charger périodiquement une page Web à l'aide de URRLIB2. En fait, je ne me soucie pas vraiment de la réponse du serveur, je voudrais seulement transmettre certaines valeurs dans l'URL au PHP. Le problème est que Python pour S60 utilise l'ancien noyau 2.5.4 Python, qui semble avoir une fuite de mémoire dans le module URRLIB2. Comme je l'ai lu, il semble également y avoir de tels problèmes dans tous les types de communications de réseau. Ce bogue a été signalé ici Il y a quelques années, tandis que des solutions de contournement ont également été postées. J'ai essayé tout ce que je pouvais trouver sur cette page, et avec l'aide de Google, mais mon téléphone est toujours sorti de la mémoire après ~ 70 de charges de pages. Étrangement, le garbege Collector ne semble pas faire de différence non plus, sauf rendre mon script beaucoup plus lentement. On dit que, que le noyau (3.1) le plus récent résout ce problème, mais malheureusement, je ne peux malheureusement pas attendre une année (ou plus) pour le port S60.
Voici comment mon script s'occupe de l'ajout de chaque petit tour I J'ai trouvé:
p>
Toute suggestion, comment le faire fonctionner pour toujours sans obtenir l'erreur "Impossible d'attribuer la mémoire"?
Merci d'avance,
Bravo, B_M P> Mise à jour: strong>
J'ai réussi à se connecter 92 fois avant de sortir de la mémoire, mais ce n'est toujours pas assez bon. P> update2: strong>
Essayé la méthode de la prise comme suggéré plus tôt, il s'agit de la deuxième meilleure solution (erronée) jusqu'à présent: p> p>
J'ai essayé aussi les petites astuces, d'en haut aussi. Le fil se ferme après ~ 50 Uploads (le téléphone dispose de 50 Mo de mémoire, évidemment, la coque Python n'a pas.) P> Mise à jour forte>:
Je pense que je me rapproche de la solution! J'ai essayé d'envoyer plusieurs données sans fermer et réouvrir la prise. Cela peut être la clé car cette méthode ne laissera qu'un descripteur de fichier ouvert. Le problème est: p> p>
*: Message d'erreur: 10053, logiciel a provoqué la connexion Abort de la connexion P>
7 Réponses :
Cela semble être une solution de contournement (très!) hacky, mais un peu de googling a trouvé ce commentaire sur le problème:
Apparemment ajouter f.fin (1) code> arrêtera la fuite! p>
import urllib2
f = urllib2.urlopen('http://www.google.com')
f.read(1)
f.close()
envisagez d'utiliser le niveau bas API de socket (associé HOWTO ) au lieu de 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)
Merci pour votre réponse, j'ai essayé celui-ci, mais cela semble être le même problème. Je ne suis pas encore sûr, car je n'ai pas vu l'erreur (éventuellement à cause du nouveau fil), mais cela cesse de rafraîchir après 52 mises à jour.
Utilisation du code de test suggéré par votre lien, j'ai testé mon installation Python et a confirmé qu'il fuit en effet. Mais, si, comme @Russell suggéra, je mettais chaque urlopen code> dans son propre processus, le système d'exploitation devrait em> nettoyer les fuites de mémoire. Dans mes tests, mes tests, mes objets inaccessibles et des fichiers ouverts restent plus ou moins constants. J'ai divisé le code en deux fichiers:
Connection.py h3>
###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()
Au début, j'ai mal compris la suggestion de Russel, j'ai essayé des threads séparés au lieu de processus distincts. Je développe l'application à un téléphone Nokia (PYS60), je ne pense pas qu'il est possible de mettre en œuvre votre solution. Cependant, cela devrait fonctionner bien sur une machine Linux. Merci pour vos efforts, je l'apprécie.
Cela ne vous fuit pas avec Python 2.6.1 sur un Mac. Quelle version utilisez-vous?
BTW, votre programme ne fonctionne pas en raison de quelques fautes de frappe. Voici celui qui fonctionne: P>
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
Selon la Wikipedia, le dernier PYS60 utilise le noyau de phython 2.5.4, la syntaxe a l'air bien, mais cela ne vient pas de mon code, il est légèrement simplifié
Oui, il est légèrement simplifié, mais cela fait toujours ce que vous vouliez.
Selon la version Plate-forme et Python, Python pourrait ne pas libérer la mémoire à OS. Voir ce fil Stackoverflow . Cela dit, Python ne doit pas consommer sans fin de la mémoire. Juger du code que vous utilisez, il semble être un bogue dans Python Runtime sauf si em>, urllib / sockets utilise des globaux que je ne crois pas que cela ne le fait pas - le blâmer sur Python sur S60! p>
Avez-vous considéré que d'autres sources de fuites de mémoire? Fichier de journal sans fin ouvert, augmentation de la matrice ou smth de l'argent comme ça? Si c'est vraiment un bogue dans l'interface des sockets, votre seule option consiste à utiliser l'approche de sous-processus. P>
J'ai exclu toutes les autres possibilités de la fuite de mémoire. Peut-être que c'est stupide, mais n'est-il pas possible d'utiliser l'urllib du plus récent pyhon, même si le Pys60 est vieux?
Je pense Ceci est Probablement votre problème. Pour résumer ce fil, il y a une fuite de mémoire dans la recherche DNS de Pys60 et vous pouvez le contourner en déplaçant la recherche DNS en dehors de la boucle interne. P>
Cela devrait certainement fonctionner. J'ai essayé l'exemple de Google et je l'ai tué après 1400 itérations. Merci beaucoup!
L'étrange chose est que ce n'est toujours pas bon. Il se bloque après ~ 200 charges de pages, même s'il n'y a qu'une seule recherche DNS. J'ai essayé l'exemple sur la page Forum.Nokia que vous avez liées et ce n'est pas bon.
Il existe un cycle de référence dans Urllib2 créé dans urllib2.py:1216. Le problème est en cours et existe depuis 2009. https://bugs.python.org/issue1208304 P>
Cela aurait dû être un commentaire
Je ne connais pas l'environnement d'exécution, mais il serait possible d'étendre la charge comme un processus séparé à chaque fois et de laisser le nettoyage du processus d'exploitation s'occuper de la fuite?
Cela pourrait être une bonne idée, merci, je vais essayer d'essayer de vous tenir au courant.
Essayez de mettre la chose entière dans une fonction et d'appeler cette fonction dans un
pendant code> boucle. Les variables locales devraient i> expirer dans ce cas, espérons-le enlever la fuite ...
Désolé, il suffit de tester cela, ça ne marche pas ...
Il suffit de tester l'idée de Russell Borogove: Le problème est que Python ne peut pas terminer le fil qui ouvre la connexion, donc dans ce cas, la mémoire remplit avec des filets suspendus au lieu de descripteurs d'Urllibfile. Je viens de passer deux heures de débogage de cette ... :(
@B_M: essayez de frayer un processus avec
Fourche code>; Je suis à peu près sûr que les threads partageront des descripteurs de fichiers.
@Brian: S60 ne prend pas en charge cette fonction, elle a également été omise du port Python.
@B_M: Cela ne vous laissait pas beaucoup d'options, n'est-ce pas? :) Je suppose que S60 ne prend pas en charge
EXEC code>, non plus. Avez-vous envisagé d'appeler l'équivalent de la bibliothèque C pour une communication de socket via
CTYPES CODE>, (ou rédigez également la communication de la prise en C et appelant cela)?
Euh, je n'ai pas, en fait, j'utilise Python, car c'est facile. Après des mois de programmation dans de telles langues charmantes telles que Python ou PHP, je n'ai pas envie de revenir au Good Ol 'C. Si c'est la seule option à gauche, je vais regarder dans ça ...
J'ai mis à jour le premier post, n'importe qui sur le problème légèrement modifié?