FTP - Datei mit GET oder RECV laden

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
f3yb4la
User
Beiträge: 11
Registriert: Samstag 8. Februar 2020, 15:13

Hallo liebes Forum,

gleich vorweg - bin absoluter Neueinsteiger in Python und probiere mich gerade an meinem ersten Skript.

Bin mittlerweile schier am Verzweifeln. Möchte eine Datei von einem FTP Server eines Solarwechselrichters laden. "Händisch" via cmd ist schon alles mal durchgespielt und funktioniert, nur leider nicht über das Python Skript. Problem ist, dass vom Server nur GET und RECV unterstützt werden.

Hab schon viel versucht von ftp.retrbinary über ftp.sendcmd, die ftputil lib bis urllib.urlretreive... alles ohne Erfolg.

Könnt ihr mir also helfen eine einfache log datei via GET oder RECV vom Server zu laden?

Danke!
Benutzeravatar
sparrow
User
Beiträge: 4186
Registriert: Freitag 17. April 2009, 10:28

In der Standardbibliothek ist ein Modul zum Umgang mit FTP: ftplib
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Was hast Du genau versucht und was war die Fehlermeldung? FTP kann hakelig sein und ohne die genauen Meldungen kann man schlecht helfen.
f3yb4la
User
Beiträge: 11
Registriert: Samstag 8. Februar 2020, 15:13

Danke für die schnellen Antworten. Verwende schon die ftplib.

Hier mal die Fehler:
Traceback (most recent call last):
File "test2.py", line 64, in <module>
ftp.retrbinary('RECV 08.log', open(filename, "wb").write)
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 425, in retrbinary
with self.transfercmd(cmd, rest) as conn:
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 382, in transfercmd
return self.ntransfercmd(cmd, rest)[0]
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 342, in ntransfercmd
host, port = self.makepasv()
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 320, in makepasv
host, port = parse227(self.sendcmd('PASV'))
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 275, in sendcmd
return self.getresp()
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 238, in getresp
resp = self.getmultiline()
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 224, in getmultiline
line = self.getline()
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 206, in getline
line = self.file.readline(self.maxline + 1)
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\socket.py", line 669, in readinto
return self._sock.recv_into(b)
ConnectionResetError: [WinError 10054] Eine vorhandene Verbindung wurde vom Remotehost geschlossen

Schicke morgen nochmal ein Fehlerprotokoll.

Danke für die Hilfe!
Benutzeravatar
__blackjack__
User
Beiträge: 13071
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@f3yb4la: Wie kommst Du auf GET oder RECV? Das sind beides keine gültigen Kommandos. Du willst RETR verwenden. Hast Du die Dokumentation des `ftplib`-Moduls mal angeschaut? Da ist gleich am Anfang ein Beispiel.

Das mit dem ``open("dateiname", "rb").write`` sollte man nicht machen, weil man auf diese Weise die Datei nicht wieder schliessen kann. Das sollte man aber tun.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
f3yb4la
User
Beiträge: 11
Registriert: Samstag 8. Februar 2020, 15:13

Wie komme ich auf GET oder RECV - Hab das ganze ja vorab über cmd probiert und da wurde RETR als ungültiger Befehl quittiert. Über ? wird die Liste der zulässigen Befehle ausgegeben und da war eben GET und RECV aufgelistet. Mit beiden Kommandos hab ich das File lokal kopiert bekommen. Daher war meine (vielleicht falsche) Annahme, dass ich einen der beiden Befehle auch über Python absetzen muss.
Benutzeravatar
__blackjack__
User
Beiträge: 13071
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@f3yb4la: Du vermischt hier Kommandos von irgendeinem FTP-Client mit den Kommandos die im FTP-Protokoll definiert sind.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
f3yb4la
User
Beiträge: 11
Registriert: Samstag 8. Februar 2020, 15:13

Ok, auch wenn ich da was vermische - wie würde es denn richtig gehen?
Wie würdet ihr das Problem lösen?
__deets__
User
Beiträge: 14523
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hast du denn RETR versucht?
f3yb4la
User
Beiträge: 11
Registriert: Samstag 8. Februar 2020, 15:13

Ja - sowohl als Argument in der ftp.retrbinary als auch direkt über die Konsole. Ging beides mal nicht.
__deets__
User
Beiträge: 14523
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was heißt denn geht nicht? In dem Code oben steht ein “RECV” vor dem Dateinamen. Gehört das dahin? Und wenn nicht, was passiert ohne?
Benutzeravatar
sparrow
User
Beiträge: 4186
Registriert: Freitag 17. April 2009, 10:28

Zeig doch mal deinen Code und die Fehlermeldung.
Wir würden das so lösen, wie es in der Dokumentation steht.
f3yb4la
User
Beiträge: 11
Registriert: Samstag 8. Februar 2020, 15:13

Danke nochmal für die Rückmeldungen.

Das wäre der Code

import ftplib
import os

ipadr = '192.168.178.99'
ftp_user = 'refu'
ftp_passwd = 'EE0129'

ftp = ftplib.FTP(ipadr, ftp_user, ftp_passwd, timeout=100)
ftp.cwd('/data/logger/2020/02')
filedata = open('09.log', 'wb')
ftp.retrbinary('RETR 09.log', filedata.write)
filedata.close()
ftp.quit()

und hier wäre die Ausgabe

Traceback (most recent call last):
File "test3.py", line 11, in <module>
ftp.retrbinary('RETR 09.log', filedata.write)
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 425, in retrbinary
with self.transfercmd(cmd, rest) as conn:
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 382, in transfercmd
return self.ntransfercmd(cmd, rest)[0]
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 342, in ntransfercmd
host, port = self.makepasv()
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 320, in makepasv
host, port = parse227(self.sendcmd('PASV'))
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 275, in sendcmd
return self.getresp()
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 238, in getresp
resp = self.getmultiline()
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 224, in getmultiline
line = self.getline()
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 206, in getline
line = self.file.readline(self.maxline + 1)
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\socket.py", line 669, in readinto
return self._sock.recv_into(b)
ConnectionResetError: [WinError 10054] Eine vorhandene Verbindung wurde vom Remotehost geschlossen

Hab mich an den Beispielen die man so im Netz findet orientiert und komme einfach nicht drauf was hier falsch ist.
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Das Kommando fliegt schon bei PASV raus, was darauf hindeutet, dass der FTP-Server keinen Passiv-Modus unterstützt.
Du brauchst also ftp.set_pasv(False).
Und eine Datei mit dem Namen "RET 09.log" gibt es wahrscheinlich nicht.
Benutzeravatar
__blackjack__
User
Beiträge: 13071
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Grmpf, vielleicht sollten die helfenden auch mal in die Dokumentation schauen, da ist gleich am Anfang ein entsprechendes Beispiel: RETR ist ein FTP-Befehl und der muss da stehen. Nicht nur der Dateiname, sondern auch der FTP-Befehl davor. Komische API, ist aber so.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
f3yb4la
User
Beiträge: 11
Registriert: Samstag 8. Februar 2020, 15:13

Hallo,

Danke für den Hinweis bzgl. des passiven Modus. Wird morgen ausprobiert.

Hab hier noch die Ergebnisse aus der Console wo ich ein bisschen gespielt habe.

ftp> ls
200 Port command okay
150 Opening data connection.
.
..
01.log
02.log
03.log
04.log
05.log
06.log
07.log
08.log
09.log
226 Transfer complete.
FTP: 82 Bytes empfangen in 0.03Sekunden 3.15KB/s
ftp> ls 08.log
200 Port command okay
150 Opening data connection.
08.log
226 Transfer complete.
FTP: 11 Bytes empfangen in 0.00Sekunden 3.67KB/s
ftp> ?
Befehle können abgekürzt werden. Befehle sind:

! delete literal prompt send
? debug ls put status
append dir mdelete pwd trace
ascii disconnect mdir quit type
bell get mget quote user
binary glob mkdir recv verbose
bye hash mls remotehelp
cd help mput rename
close lcd open rmdir
ftp> type
Dateien werden im ascii-Modus übertragen.
ftp> user
Benutzername refu
331 User name okay, need password.
Kennwort:
230 Logged in
ftp> status
Verbindung mit 192.168.178.99 wurde hergestellt.
Typ: ascii; Verbose: EIN ; Bell: AUS ; Prompt: EIN ; Glob: EIN
Debug: AUS ; Hash: AUS
ftp> remotehelp
214- The following commands are recognized:
abor acct cwd dele form help
list mkd nlst noop opts pass
pasv port pwd quit retr rmd
rnfr rnto stor site syst type
user xcwd xmkd xpwd xrmd
214 Direct comments to Embedded Access Inc.
ftp> pasv
Ungültiger Befehl
ftp> status
Verbindung mit 192.168.178.99 wurde hergestellt.
Typ: ascii; Verbose: EIN ; Bell: AUS ; Prompt: EIN ; Glob: EIN
Debug: AUS ; Hash: AUS
ftp>


Wenn ich die Ausgabe der remotehelp richtig verstehe müsste sowohl pasv als auch retr akzeptiert werden.
__deets__
User
Beiträge: 14523
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich vermute mal die Hilfe ist nicht so gut, dass sie deaktivierte Kommandos entfernt. Denn der Code ist ja klar daran gescheitert.
f3yb4la
User
Beiträge: 11
Registriert: Samstag 8. Februar 2020, 15:13

Der Test mit dem Passive Mode verschiebt sich arbeitsbedingt auf Donnerstag.

Kann ich darüber hinaus noch was probieten? Hat noch jemand einen Vorschlag?
f3yb4la
User
Beiträge: 11
Registriert: Samstag 8. Februar 2020, 15:13

Es funktioniert! Es lag am passive mode.

Ausführliche Log's poste ich noch.

Danke an alle für die Hilfe!
f3yb4la
User
Beiträge: 11
Registriert: Samstag 8. Februar 2020, 15:13

Das Testprogramm schaut so aus:

import ftplib
import os

ipadr = '192.168.178.99'
ftp_user = 'refu'
ftp_passwd = 'EE0129'

ftp = ftplib.FTP(ipadr, ftp_user, ftp_passwd, timeout=100)
ftp.set_debuglevel(2)
ftp.cwd('/data/logger/2020/02')
filedata = open('11.log', 'wb')
ftp.set_pasv(False)
ftp.retrbinary('RETR 09.log', filedata.write)
filedata.close()
ftp.quit()

Als Ausgabe folgt dann:

*cmd* 'CWD /data/logger/2020/02'
*put* 'CWD /data/logger/2020/02\r\n'
*get* '257 "\\data\\logger\\2020\\02" is the current directory\n'
*resp* '257 "\\data\\logger\\2020\\02" is the current directory'
*cmd* 'TYPE I'
*put* 'TYPE I\r\n'
*get* '200 Type Binary.\n'
*resp* '200 Type Binary.'
*cmd* 'PORT 192,168,178,86,221,61'
*put* 'PORT 192,168,178,86,221,61\r\n'
*get* '200 Port command okay\n'
*resp* '200 Port command okay'
*cmd* 'RETR 09.log'
*put* 'RETR 09.log\r\n'
*get* '150 Opening data connection.\n'
*resp* '150 Opening data connection.'
*get* '226 File sent OK - 11288 bytes in 0.128 sec\n'
*resp* '226 File sent OK - 11288 bytes in 0.128 sec'
*cmd* 'QUIT'
*put* 'QUIT\r\n'
*get* '221 Goodbye.\n'
*resp* '221 Goodbye.'

wird oben ftp.set_pasv(False) auskommentiert ergibt sich folgendes Bild:

*cmd* 'CWD /data/logger/2020/02'
*put* 'CWD /data/logger/2020/02\r\n'
*get* '257 "\\data\\logger\\2020\\02" is the current directory\n'
*resp* '257 "\\data\\logger\\2020\\02" is the current directory'
*cmd* 'TYPE I'
*put* 'TYPE I\r\n'
*get* '200 Type Binary.\n'
*resp* '200 Type Binary.'
*cmd* 'PASV'
*put* 'PASV\r\n'
Traceback (most recent call last):
File "test3.py", line 13, in <module>
ftp.retrbinary('RETR 09.log', filedata.write)
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 425, in retrbinary
with self.transfercmd(cmd, rest) as conn:
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 382, in transfercmd
return self.ntransfercmd(cmd, rest)[0]
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 342, in ntransfercmd
host, port = self.makepasv()
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 320, in makepasv
host, port = parse227(self.sendcmd('PASV'))
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 275, in sendcmd
return self.getresp()
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 238, in getresp
resp = self.getmultiline()
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 224, in getmultiline
line = self.getline()
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\ftplib.py", line 206, in getline
line = self.file.readline(self.maxline + 1)
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\lib\socket.py", line 669, in readinto
return self._sock.recv_into(b)
ConnectionResetError: [WinError 10054] Eine vorhandene Verbindung wurde vom Remotehost geschlossen


Danke nochmals für die Hilfe!
Antworten