Python multitraitement: TypeError: chaîne de caractères Unicode ou un objet, NoneType trouvé
Je suis tenté de télécharger un ensemble de répertoire ftp en parallèle.
#!/usr/bin/python
import sys
import datetime
import os
from multiprocessing import Process, Pool
from ftplib import FTP
curYear=""
remotePath =""
localPath = ""
def downloadFiles (remotePath,localPath):
splitted = remotePath.split('/');
host= splitted[2]
path='/'+'/'.join(splitted[3:])
ftp = FTP(host)
ftp.login()
ftp.cwd(path)
filenames = ftp.nlst()
total=len(filenames)
i=0
pool = Pool()
for filename in filenames:
local_filename = os.path.join(localPath,filename)
pool.apply_async(downloadFile, (filename,local_filename,ftp))
#downloadFile(filename,local_filename,ftp);
i=i+1
pool.close()
pool.join()
ftp.close()
def downloadFile(filename,local_filename,ftp):
file = open(local_filename, 'wb')
ftp.retrbinary('RETR '+ filename, file.write)
file.close()
def getYearFromArgs():
if len(sys.argv) >= 2 and sys.argv[1] == "Y":
year = sys.argv[2]
del sys.argv[1:2]
else:
year = str(datetime.datetime.now().year)
return year
def assignGlobals():
global p
global remotePath
global localPath
global URL
global host
global user
global password
global sqldb
remotePath = 'ftp://ftp3.ncdc.noaa.gov/pub/data/noaa/isd-lite/%s/' % (curYear)
localPath = '/home/isd-lite/%s/' % (curYear)
def main():
global curYear
curYear=getYearFromArgs()
assignGlobals()
downloadFiles(remotePath,localPath)
if __name__ == "__main__":
main()
Mais je bénéficier de cette exception:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib64/python2.6/threading.py", line 532, in __bootstrap_inner
self.run()
File "/usr/lib64/python2.6/threading.py", line 484, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/lib64/python2.6/multiprocessing/pool.py", line 225, in _handle_tasks
put(task)
TypeError: expected string or Unicode object, NoneType found
Si je commente cette ligne:
pool.apply_async(downloadFile, (filename,local_filename,ftp)
et supprimez le commentaire sur cette ligne:
downloadFile(filename,local_filename,ftp);
Alors qu'il fonctionne très bien mais c'est lent et n'est pas multithread.
Ce code ne s'exécute pas comme il est écrit (il y a des nom de variable erreurs dans
Bien, j'ai mis à jour mon post.
essayez:
Est-ce qui se passe dans le premier thread lui-même, pouvez-vous essayer de mettre une impression à l'intérieur
downloadFiles
). Vous pouvez poster code de travail et de montrer un exemple d'appel de downloadFiles
qui illustre le problème?Bien, j'ai mis à jour mon post.
essayez:
from multiprocessing.dummy import Pool
qui utilise des threads au lieu de processus comme une solution de rechange rapide si cela fonctionne, alors le problème peut être dans l'initialisation/passage de quelques objets (p. ex., ftp
de processus enfants. Envelopper downloadFile()
corps dans try/except
bloc journal des exceptions dans les cas où cette version de multiprocessing
signale de manière incorrecte.Est-ce qui se passe dans le premier thread lui-même, pouvez-vous essayer de mettre une impression à l'intérieur
downloadFile()
et voir.OriginalL'auteur Mike Furlender | 2013-01-08
Vous devez vous connecter pour publier un commentaire.
Mise À Jour, Le 9 Mai 2014:
J'ai établi le précise limitation. Il est possible d'envoyer des objets dans les limites du processus pour les processus de travail aussi longtemps que les objets peuvent être traitées par Python pickle installation. Le problème que j'ai décrite dans mon original de la réplique s'est produite parce que je tente d'envoyer un descripteur de fichier pour les travailleurs. Une rapide expérience démontre pourquoi cela ne fonctionne pas:
Donc, si vous êtes à la rencontre de l'Python erreur qui vous a amené à trouver ce Débordement de Pile question, assurez-vous que toutes les choses que vous envoyez dans les limites du processus peuvent être traitées.
Réponse originale à cette question:
Je suis un peu en retard pour répondre. Cependant, j'ai couru dans le même message d'erreur que le posteur d'origine, tout en essayant d'utiliser Python module multiprocessing. Je vais enregistrer mes résultats ainsi que toute autre personne qui tombe sur ce thread a quelque chose à essayer.
Dans mon cas, l'erreur s'est produite à cause de ce que je tente d'envoyer à l'ensemble des travailleurs: j'ai essayé de passer un tableau d'objets file pour la piscine, les travailleurs à mâcher. C'est apparemment trop pour envoyer dans les limites du processus en Python. J'ai résolu le problème en envoyant la piscine travailleurs dictionnaires qui a précisé d'entrée et de sortie nom de fichier de chaînes.
Il semble donc que l'objet iterable que vous fournissez à la fonction comme
apply_async
(j'ai utilisémap()
etimap_unordered()
) peut contenir une liste de nombres ou de chaînes de caractères, ou même un dictionnaire détaillé structure de données (aussi longtemps que les valeurs ne sont pas des objets).Dans votre cas:
ftp
est un objet, qui peut être à l'origine du problème. Comme solution de contournement, je vous recommande d'envoyer les paramètres pour le travailleur (qui ressemble à unehost
etpath
dans ce cas) et laissez le travailleur instancier l'objet et de traiter avec le nettoyage.Je ne suis pas sûr de ce que exactement les limites. Ce que j'ai décrit est ce qui a résolu mon problème.
Ouais j'ai eu à faire un travail autour de trop, tout comme vous (seulement j'ai fini à l'aide de threads au lieu de cela). Est-ce une limitation due à la GIL? Je suis en train de penser si Python est thread-safe, il pourrait le faire.
J'ai pensé à elle aujourd'hui, vous pouvez envoyer quoi que ce soit dans les limites du processus tant qu'il peut être nettoyée. Je vais mettre à jour ma réponse à inclure cette information.
Je suis en train d'essayer d'obtenir randints de mon parallèle des moteurs, il suffit de faire apply_async(np.aléatoire.randint, 5), mais à obtenir la même erreur. Ce n'est pas le décapage ici?
OriginalL'auteur Multimedia Mike
Avez-vous essayé:
Le prototype est :
OriginalL'auteur ATOzTOA