Python 2.7: получить файл netCDF4 с помощью ftplib

Вот моя проблема: я загружаю некоторые файлы netCDF4 с FTP-сервера двумя разными способами: через FileZilla и через скрипт Python 2.7 с использованием ftplib.

Код скрипта Python (работает в Windows):

# download the file
try:
    ftp = FTP(server_address)
    ftp.login(server_login, server_pass)
    filepath = 'the_remote_rep/myNetCDF4File.nc'
    filename = 'myNetCDF4File.nc'
    local_dir = 'toto'
    new_file = open('%s/%s' % (local_dir, filename), "w")
    ftp.retrbinary('RETR %s' % filepath, new_file.write)
    ftp.close()
    new_file.close()
except Exception as e:
    print("Error FTP : '" + str(e) + "'")

# update title into the file
try:
    fname = 'toto/myNetCDF4File.nc'
    dataset = netCDF4.Dataset(fname, mode='a')
    setattr(dataset, 'title', 'In Situ Observation Re-Analysis')
    dataset.close()
except Exception as e:
    print("Error netCDF4 : '" + str(e) + "'")

Затем я получаю это сообщение:

Ошибка netCDF4: '[Errno 22] Недопустимый аргумент: 'toto/myNetCDF4File.nc''

Когда я пробую второй блок кода с файлом netCDF4, загруженным через FileZilla (тот же файл, например), ошибки нет. Кроме того, когда я пытаюсь получить версию файла netCDF с помощью «ncdump -k», вот ответ (ОК с другим файлом):

ncdump: myNetCDF4File.nc: неверный аргумент

Кроме того, файлы не имеют одинакового размера в зависимости от метода:

  • FileZilla : 22 972 Ко

  • Python ftplib: 23 005 Ko

Это проблема со стороны ftplib при записи полученного файла? Или я пропустил какие-то параметры для корректной кодировки файла?

Заранее спасибо.

РЕДАКТИРОВАТЬ: подробные сообщения от FileZilla:

...
Response:   230 Login successful.
Trace:  CFtpLogonOpData::ParseResponse() in state 5
Trace:  CControlSocket::SendNextCommand()
Trace:  CFtpLogonOpData::Send() in state 9
Command:    OPTS UTF8 ON
Trace:  CFtpControlSocket::OnReceive()
Response:   200 Always in UTF8 mode.
Trace:  CFtpLogonOpData::ParseResponse() in state 9
Status: Logged in
Trace:  Measured latency of 114 ms
Trace:  CFtpControlSocket::ResetOperation(0)
Trace:  CControlSocket::ResetOperation(0)
Trace:  CFtpLogonOpData::Reset(0) in state 14
Trace:  CFtpControlSocket::FileTransfer()
Trace:  CControlSocket::SendNextCommand()
Trace:  CFtpFileTransferOpData::Send() in state 0
Status: Starting download of /INSITU_OBSERVATIONS/myNetCDF4File.nc
Trace:  CFtpChangeDirOpData::Send() in state 0
Trace:  CFtpControlSocket::ResetOperation(0)
Trace:  CControlSocket::ResetOperation(0)
Trace:  CFtpChangeDirOpData::Reset(0) in state 0
Trace:  CFtpFileTransferOpData::SubcommandResult(0) in state 1
Trace:  CControlSocket::SendNextCommand()
Trace:  CFtpFileTransferOpData::Send() in state 5
Trace:  CFtpRawTransferOpData::Send() in state 2
Command:    PASV
Trace:  CFtpControlSocket::OnReceive()
Response:   227 Entering Passive Mode (193,68,190,45,179,16).
Trace:  CFtpRawTransferOpData::ParseResponse() in state 2
Trace:  CControlSocket::SendNextCommand()
Trace:  CFtpRawTransferOpData::Send() in state 4
Trace:  Binding data connection source IP to control connection source IP 134.xx.xx.xx
Command:    RETR myNetCDF4File.nc
Trace:  CTransferSocket::OnConnect
Trace:  CFtpControlSocket::OnReceive()
Response:   150 Opening BINARY mode data connection for myNetCDF4File.nc (9411620 bytes).
Trace:  CFtpRawTransferOpData::ParseResponse() in state 4
Trace:  CControlSocket::SendNextCommand()
Trace:  CFtpRawTransferOpData::Send() in state 5
Trace:  CTransferSocket::TransferEnd(1)
Trace:  CFtpControlSocket::TransferEnd()
Trace:  CFtpControlSocket::OnReceive()
Response:   226 Transfer complete.
Trace:  CFtpRawTransferOpData::ParseResponse() in state 7
Trace:  CFtpControlSocket::ResetOperation(0)
Trace:  CControlSocket::ResetOperation(0)
Trace:  CFtpRawTransferOpData::Reset(0) in state 7
Trace:  CFtpFileTransferOpData::SubcommandResult(0) in state 7
Trace:  CFtpControlSocket::ResetOperation(0)
Trace:  CControlSocket::ResetOperation(0)
Trace:  CFtpFileTransferOpData::Reset(0) in state 7
Status: File transfer successful, transferred 9 411 620 bytes in 89 seconds
Status: Disconnected from server
Trace:  CFtpControlSocket::ResetOperation(66)
Trace:  CControlSocket::ResetOperation(66)

person Rasta 29    schedule 12.03.2019    source источник
comment
Какая строка выдает ошибку? + Покажите нам подробный файл журнала FileZilla.   -  person Martin Prikryl    schedule 12.03.2019
comment
Строка, содержащая набор данных = netCDF4.Dataset(fname, mode='a').   -  person Rasta 29    schedule 12.03.2019
comment
Итак, когда вы заменяете ftp.retrbinary на file.write (например, копируя существующий локальный файл) - вы получаете ту же ошибку?   -  person Martin Prikryl    schedule 12.03.2019
comment
Пожалуйста, добавьте также журнал отладки из ftplib, т.е. ftp.set_debuglevel(2). Кроме того, размер файла, указанный в выводе filezilla (9411620 байт), совершенно не соответствует размеру файла, который вы указали в своем вопросе (22 972 Ko - какая бы ни была единица Ko).   -  person Steffen Ullrich    schedule 12.03.2019


Ответы (1)


На самом деле это проблема бинарной конфигурации (спасибо за ваши вопросы).

Я добавил ftp.voidcmd('TYPE I') перед получением файла с помощью ftplib, затем я изменил параметр записи локального файла как new_file = open('%s/%s' % (local_ftp_path, filename), "wb"), чтобы указать, что это двоичный файл.

Теперь файл доступен для чтения после загрузки через ftplib и имеет тот же размер, что и при загрузке из FileZilla.

Благодаря вашему вкладу.

person Rasta 29    schedule 12.03.2019
comment
Нет необходимости в ftp.voidcmd('TYPE I') -- retrbinary уже делает это. - person Martin Prikryl; 12.03.2019