2013-01-08 16 views
13

मैं समांतर में एक संपूर्ण ftp निर्देशिका डाउनलोड करने का प्रयास कर रहा हूं।पायथन मल्टीप्रोसेसिंग: टाइप एरर: अपेक्षित स्ट्रिंग या यूनिकोड ऑब्जेक्ट, कोई नहीं टाइप

#!/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() 

लेकिन मैं इस अपवाद प्राप्त करें:

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 

अगर मैं इस लाइन बाहर टिप्पणी:

pool.apply_async(downloadFile, (filename,local_filename,ftp) 

और इस लाइन पर टिप्पणी को निकाल दें: फिर

downloadFile(filename,local_filename,ftp); 

यह ठीक काम करता है लेकिन यह धीमा है और नहीं बहु-क्रम।

+0

यह कोड लिखित के रूप में नहीं चलाया जाता है ('डाउनलोडफाइल' में परिवर्तनीय नाम त्रुटियां हैं)। क्या आप वर्किंग कोड पोस्ट कर सकते हैं और 'डाउनलोडफाइल' का नमूना कॉल दिखा सकते हैं जो समस्या का प्रदर्शन करता है? –

+0

ठीक है - मैंने अपनी पोस्ट संशोधित की। –

+0

आज़माएं: 'multiprocessing.dummy आयात पूल' से जो प्रक्रियाओं के बजाय थ्रेड का उपयोग त्वरित कार्यवाही के रूप में करता है, यदि यह काम करता है तो समस्या कुछ ऑब्जेक्ट्स प्रारंभ/पास करने में हो सकती है जैसे कि बच्चे प्रक्रियाओं के लिए 'ftp'। 'मल्टीप्रोसेसिंग' के इस संस्करण को गलत तरीके से रिपोर्ट करने के मामले में अपवाद लॉग करने के लिए 'कोशिश/छोड़कर' ब्लॉक में 'डाउनलोडफाइल() 'निकाय को लपेटें। – jfs

उत्तर

-1

आप की कोशिश की है:

pool.apply_async(downloadFile, args=(filename,local_filename,ftp)) 

प्रोटोटाइप है:

apply_async(func, args=(), kwds={}, callback=None) 
18

अद्यतन, 9 मई, 2014:

मैं सटीक सीमा निर्धारित किया है। जब तक वस्तुओं को Python's pickle facility द्वारा उठाया जा सकता है, तब तक प्रक्रिया प्रक्रियाओं में प्रक्रिया सीमाओं में वस्तुओं को भेजना संभव है। मेरे मूल उत्तर में जो समस्या मैंने वर्णित की है, वह इसलिए हुआ क्योंकि मैं श्रमिकों को फाइल हैंडल भेजने की कोशिश कर रहा था। एक त्वरित प्रयोग दर्शाता है क्यों यह काम नहीं करता है:

>>> f = open("/dev/null") 
>>> import pickle 
>>> pickle.dumps(f) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.7/pickle.py", line 1374, in dumps 
    Pickler(file, protocol).dump(obj) 
    File "/usr/lib/python2.7/pickle.py", line 224, in dump 
    self.save(obj) 
    File "/usr/lib/python2.7/pickle.py", line 306, in save 
    rv = reduce(self.proto) 
    File "/usr/lib/python2.7/copy_reg.py", line 70, in _reduce_ex 
    raise TypeError, "can't pickle %s objects" % base.__name__ 
TypeError: can't pickle file objects 

इस प्रकार, आप अजगर त्रुटि जो आप इस स्टैक ओवरफ़्लो सवाल को खोजने के लिए नेतृत्व का सामना कर रहे हैं, सुनिश्चित करें कि सभी चीजें आप प्रक्रिया सीमाओं के पार भेज रहे हैं बनाने के मसालेदार किया जा सकता है।

मूल जवाब:

मैं जवाब देने के लिए देर से एक सा रहा हूँ। हालांकि, मैं पाइथन के मल्टीप्रोसेसिंग मॉड्यूल का उपयोग करने के दौरान मूल पोस्टर के रूप में एक ही त्रुटि संदेश में भाग गया। मैं अपने निष्कर्ष रिकॉर्ड करूंगा ताकि कोई भी जो इस धागे पर ठोकर खा सके, कोशिश करने के लिए कुछ है।

मेरे मामले में, त्रुटियों के कारण हुई जो मैं श्रमिकों के पूल में भेजने की कोशिश कर रहा था: मैं पूल श्रमिकों को चबाने के लिए फ़ाइल ऑब्जेक्ट्स की एक सरणी पास करने की कोशिश कर रहा था। यह पाइथन में प्रक्रिया सीमाओं को भेजने के लिए जाहिर है। मैंने पूल श्रमिकों को भेजकर समस्या हल की जो निर्दिष्ट इनपुट और आउटपुट फ़ाइल नाम स्ट्रिंग्स।

तो ऐसा लगता है कि iterable है कि आप समारोह जैसे apply_async (मैं map() और imap_unordered() प्रयोग किया जाता) को आपूर्ति जब तक मान नहीं कर रहे 'नंबर या तार, या यहां तक ​​कि एक विस्तृत शब्दावली डेटा संरचना की सूची हो सकती है (टी वस्तुओं)।

आपके मामले में:

pool.apply_async(downloadFile, (filename,local_filename,ftp)) 

ftp एक वस्तु है, जो समस्या का कारण हो सकता है। एक कामकाज के रूप में, मैं कार्यकर्ता को पैरामीटर भेजने की सिफारिश करता हूं (इस मामले में host और path जैसा दिखता है) और कार्यकर्ता को ऑब्जेक्ट को तुरंत चालू करने और सफाई के साथ सौदा करने दें।

+0

आप मल्टीप्रोसेसिंग के साथ कार्यों को गंभीरता से ऑब्जेक्ट्स मैप नहीं कर सकते हैं? – CornSmith

+0

मुझे यकीन नहीं है कि सटीक सीमाएं क्या हैं। मैंने जो वर्णन किया वह मेरी समस्या का समाधान करता है। –

+0

हाँ मुझे आपके जैसे काम भी करना था (केवल मैं इसके बजाय धागे का उपयोग कर समाप्त हुआ)। क्या यह सीमा जीआईएल के कारण है? मैं सोच रहा हूं कि पाइथन थ्रेड सुरक्षित था अगर यह ऐसा कर सकता था। – CornSmith

संबंधित मुद्दे