2011-03-08 15 views
23

पाइथन न्यूब यहां कृपया मेरे साथ सहन करें। मैं एफ़टीपी के माध्यम से निर्देशिका से सभी फाइलों को डाउनलोड करने के लिए एक स्क्रिप्ट एक साथ रख रहा हूँ। मुझे यकीन है कि आप कर सकतेपायथन-एफ़टीपी निर्देशिका में सभी फाइलें डाउनलोड करें

from ftplib import FTP 
import os, sys, os.path 

def handleDownload(block): 
    file.write(block) 
    print ".", 

ddir='C:\\Data\\test\\' 
os.chdir(ddir) 
ftp = FTP('test1/server/') 

print 'Logging in.' 
ftp.login('user1\\anon', 'pswrd20') 
directory = '\\data\\test\\' 

print 'Changing to ' + directory 
ftp.cwd(directory) 
ftp.retrlines('LIST') 

print 'Accessing files' 

for subdir, dirs, files in os.walk(directory): 
    for file in files: 
     full_fname = os.path.join(root, fname); 
     print 'Opening local file ' 
     ftp.retrbinary('RETR C:\\Data\\test\\' + fname, 
         handleDownload, 
         open(full_fname, 'wb')); 
     print 'Closing file ' + filename 
     file.close(); 
ftp.close() 

: अब तक मैं कनेक्ट करने और एक फाइल लाने में कामयाब रहे, लेकिन मैं बैच में काम करने के लिए (निर्देशिका से सभी फाइलों को मिलता है) यहाँ बनाने के लिए नहीं कर पा रहे कि क्या मैं अब तक किया है बताते हैं कि यह बहुत काम नहीं करता है जब मैं इसे चलाने, तो सुधार के लिए कोई सुझाव हो सकता है बहुत सराहना

पुनश्च यह होमवर्क नहीं है: डीडी

धन्यवाद !!

उत्तर

7

यह सिर्फ एक समस्या को हल करना चाहते हैं, तो मैं wget आदेश का सुझाव दे सकता:

cd c:\destination 
wget --mirror --continue --no-host-directories --user=username --password=s3cr3t ftp://hostname/source/path/ 

--continue विकल्प बहुत खतरनाक हो सकता है अगर फ़ाइलों सर्वर पर परिवर्तन। अगर फाइलें केवल जोड़े गए हैं, तो यह बहुत दोस्ताना है।

हालांकि, अगर यह आपके लिए एक सीखने व्यायाम है और आप अपने कार्यक्रम काम करना चाहते हैं, मुझे लगता है कि आप इस लाइन को देखकर शुरू कर देना चाहिए:

for subdir, dirs, files in os.walk(directory): 

directory कर दिया गया है आपके अधिकांश कार्यक्रम में रिमोट स्रोत निर्देशिका, लेकिन os.walk() फ़ंक्शन दूरस्थ निर्देशिका पर नहीं चल सकता है। retrlines फ़ंक्शन पर दिए गए कॉलबैक का उपयोग करके, आपको लौटाई गई फाइलों पर स्वयं को पुन: सक्रिय करने की आवश्यकता है।

MLSD या NLST विकल्प LIST के बजाय NLST विकल्पों पर नज़र डालें, तो शायद उन्हें पार्स करना आसान होगा। (ध्यान दें कि एफ़टीपी वास्तव में निर्दिष्ट नहीं करता है कि सूचियों को कैसे दिखाना चाहिए; यह हमेशा एक इंसान द्वारा कंसोल पर संचालित किया जाना था, या एक विशिष्ट फ़ाइल नाम स्थानांतरित किया जाना था। ऐसे प्रोग्राम जो एफ़टीपी लिस्टिंग के साथ चालाक चीजें करते हैं जैसे उन्हें उपयोगकर्ता में प्रस्तुत करना एक जीयूआई में शायद अजीब या अस्पष्ट सर्वर के लिए विशेष केस कोड की विशाल ढेर होनी चाहिए। और दुर्भावनापूर्ण फ़ाइल नामों का सामना करते समय वे शायद कुछ बेवकूफ़ बनाते हैं।)

क्या आप इसके बजाय sftp का उपयोग कर सकते हैं? sftp में फ़ाइल लिस्टिंग को पार्स किए जाने के लिए एक विनिर्देश है, स्पष्ट रूप से उपयोगकर्ता नाम/पासवर्ड संचारित नहीं करता है, और पासिव बनाम सक्रिय कनेक्शन की विशाल परेशानी नहीं है - यह केवल एकल कनेक्शन का उपयोग करता है, जिसका अर्थ है कि यह एफ़टीपी की तुलना में अधिक फ़ायरवॉल में काम करता है।

संपादित करें: आपको retrlines फ़ंक्शन पर 'कॉल करने योग्य' ऑब्जेक्ट पास करने की आवश्यकता है। एक कॉल करने योग्य ऑब्जेक्ट या तो उस वर्ग का उदाहरण है जो __call__ विधि या फ़ंक्शन को परिभाषित करता है। जबकि समारोह का वर्णन करना आसान हो सकता है, एक वर्ग का एक उदाहरण अधिक उपयोगी हो सकता है। (आप फ़ाइल नाम एकत्र करने के लिए उदाहरण का उपयोग कर सकते हैं, लेकिन फ़ंक्शन को वैश्विक चर पर लिखना होगा। खराब।)

यहाँ सबसे सरल प्रतिदेय वस्तु में से एक है:

>>> class c: 
... def __call__(self, *args): 
... print(args) 
... 
>>> f = c() 
>>> f('hello') 
('hello',) 
>>> f('hello', 'world') 
('hello', 'world') 

यह एक नया वर्ग, c, कि एक उदाहरण विधि __call__ को परिभाषित करता है बनाता है। यह सिर्फ अपने तर्कों को काफी बेवकूफ तरीके से प्रिंट करता है, लेकिन यह दिखाता है कि हम कितनी कम बात कर रहे हैं। :)

आप कुछ होशियार चाहता था, तो यह कुछ इस तरह कर सकता है:

class handle_lines: 
    def __init__(self): 
    self.lines = [] 
    def __call__(self, *args): 
    self.lines << args[0] 

इस वर्ग की एक वस्तु के साथ कॉल iterlines, तो वस्तु की जानकारी के लिए lines सदस्य में लग रहे हो।

+0

@ सोस्टी, मेरे पोस्ट में उल्लेख किया गया 'रेट्रलाइन' फ़ंक्शन प्रलेखन के लिए एक हाइपरलिंक है :) – sarnold

+0

इसके लिए बहुत कुछ धन्यवाद, वे सभी ठोस सुझावों की तरह लगते हैं! मैं विंडोज एक्सपी पर पायथन 2.5 का उपयोग कर आईएम का उल्लेख करना भूल गया (अगर यह बिल्कुल उपयोगी है) यदि मैं एमएलएसडी विकल्प, 'ftp.retrlines (' एमएलएसडी ')' का उपयोग करता हूं, तो कोड पुनरावृत्ति के लिए काम करेगा या क्या मुझे संशोधित करने की आवश्यकता है अधिक? (यकीन है कि यह थोड़ा सा दफ़्तर लगता है लेकिन यहां नया है, याद रखें?: डीडी) – Sosti

+0

@ सोस्टी, आपको अभी भी अपना कोड संशोधित करने की आवश्यकता होगी: आप 'os.walk()' फ़ंक्शन का उपयोग नहीं कर सकते। 'Retrlines' के लिए कॉलबैक ऑब्जेक्ट को कैसे बनाना है, यह दिखाने के लिए मैं थोड़ा सा जवाब दूंगा। – sarnold

55

मैं इस दरार, इसलिए अब भावी आगंतुकों के लिए कोड के प्रासंगिक बिट पोस्टिंग प्रबंधित किया है:

filenames = ftp.nlst() # get filenames within the directory 
print filenames 

for filename in filenames: 
    local_filename = os.path.join('C:\\test\\', filename) 
    file = open(local_filename, 'wb') 
    ftp.retrbinary('RETR '+ filename, file.write) 

    file.close() 

ftp.quit() # This is the “polite” way to close a connection 

यह अजगर 2.5, Windows XP पर मेरे लिए काम किया।

+8

filenames = ftp.nlst() – nad2000

+2

अनुशंसित तरीका का उपयोग करना है: 'ftp.quose()' 'ftp.quit()' के बजाय। कृपया [यह लिंक देखें] (https://docs.python.org/2/library/ftplib.html#ftplib.FTP.quit) – Oran

-1

एक निर्देशिका डाउनलोड करने के लिए Python lib का उपयोग करने के बजाय, हम पायथन प्रोग्राम से एक डॉस स्क्रिप्ट को कॉल कर सकते हैं। डॉस स्क्रिप्ट में हम मूल ftp प्रोटोकॉल का उपयोग करेंगे जो mget *.* का उपयोग कर फ़ोल्डर से सभी फ़ाइल डाउनलोड कर सकते हैं।

fetch.bat 
ftp -s:fetch.txt 

fetch.txt 
open <ipaddress> 
<userid> 
<password> 
bin (set the mnode to binary) 
cd </desired directory> 
mget *.* 
bye 

fetch.py 
import os 
os.system("fetch.bat") 
+4

यह समाधान – m1k3y3

+1

से अधिक कामकाज है यह विंडोज़ (डॉस) – Carl

+0

के लिए भी विशिष्ट है कभी-कभी, यह मदद करता है। – JOHN

0

मैं एक नौसिखिया हूं इसलिए मैंने कोड को कुशलता से नहीं बनाया है, लेकिन मैंने इसे बनाया और परीक्षण किया कि यह काम कर रहा है। यह वही है जो मैंने ftp साइट से फ़ाइलों और फ़ोल्डरों को डाउनलोड करने के लिए किया था, लेकिन फ़ाइल संरचना में केवल सीमित गहराई है।

try: 
    a = input("Enter hostname : ") 
    b = input("Enter username : ") 
    c = input("Enter password : ") 
    from ftplib import FTP 
    import os 
    os.makedirs("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp") 
    os.chdir("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp") 
    ftp = FTP(host = a, user= b, passwd = c) 
    D = ftp.nlst() 
    for d in D: 
     l = len(d) 
     char = False 
     for i in range(0,l): 
      char = char or d[i]=="." 
     if not char: 
     ftp.cwd("..") 
     ftp.cwd("..") 
     E = ftp.nlst("%s"%(d)) 
     ftp.cwd("%s"%(d)) 
     try: 
      os.makedirs("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s"%(d)) 
     except: 
      print("you can debug if you try some more") 
     finally: 
      os.chdir("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s"%(d)) 
      for e in E: 
       l1 = len(e) 
       char1 = False 
       for i in range(0,l1): 
        char1 = char1 or e[i]=="." 
       if not char1: 
        ftp.cwd("..") 
        ftp.cwd("..") 
        F = ftp.nlst("%s/%s"%(d,e)) 
        ftp.cwd("%s/%s"%(d,e)) 
        try: 
         os.makedirs("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s\\%s"%(d,e)) 
        except: 
         print("you can debug if you try some more") 
        finally: 
         os.chdir("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s\\%s"%(d,e)) 
         for f in F: 
          if "." in f[2:]: 
           with open(f,'wb') as filef: 
            ftp.retrbinary('RETR %s' %(f), filef.write) 
          elif not "." in f: 
           try: 
            os.makedirs("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s\\%s\\%s"%(d,e,f)) 
           except: 
            print("you can debug if you try some more") 
       elif "." in e[2:]: 
        os.chdir("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s"%(d)) 
        ftp.cwd("..") 
        ftp.cwd("..") 
        ftp.cwd("..") 
        ftp.cwd("%s"%(d)) 
        with open(e,'wb') as filee: 
         ftp.retrbinary('RETR %s' %(e), filee.write) 
     elif "." in d[2:]: 
      ftp.cwd("..") 
      ftp.cwd("..") 
      os.chdir("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp") 
      with open(d,'wb') as filed: 
      ftp.retrbinary('RETR %s'%(d), filed.write) 
    ftp.close() 
    print("Your files has been successfully downloaded and saved. Bye") 
except: 
    print("try again you can do it") 
finally: 
    print("code ran") 
+0

क्या आप समझा सकते हैं कि आपका कोड कैसे/क्यों काम करता है? इससे ओपी और अन्य लोग आपकी विधियों को समझने और लागू करने में सक्षम होंगे (जहां लागू हो) कहीं और। कोड-केवल उत्तर [निराश] (http://meta.stackexchange.com/q/148272/284827) और हटाए जाने के लिए उत्तरदायी हैं। - [समीक्षा के दौरान] (http: // stackoverflow।कॉम/समीक्षा/देर से उत्तर/11704863) –

+0

क्या आपका मतलब कोड में टिप्पणियां है? – PremVijay

2

यह कोड मुझे लगता है कि ओवरकिल का थोड़ा सा हिस्सा है।

ftp.login के बाद (अजगर उदाहरण https://docs.python.org/2/library/ftplib.html से)() और स्थापित करने ftp.cwd() तुम सिर्फ उपयोग कर सकते हैं:

os.chdir(ddir) 
ls = ftp.nlst() 
count = len(ls) 
curr = 0 
print "found {} files".format(count) 
for fn in ls: 
    curr += 1 
    print 'Processing file {} ... {} of {} ...'.format(fn, curr, count) 
    ftp.retrbinary('RETR ' + fn, open(fn, 'wb').write) 

ftp.quit() 
print "download complete." 

सभी फाइलों को डाउनलोड करने के लिए।

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