Python編寫FTP自動化上傳下載腳本的實現(xiàn)指南
引言
Python提供了一個簡單而強大的方式來編寫FTP自動化腳本,利用 ftplib 庫實現(xiàn)文件的上傳和下載功能。該腳本包含連接FTP服務(wù)器、上傳文件、下載文件及自動化執(zhí)行這些任務(wù)的方法。通過實際案例和代碼示例,本指南展示了如何快速上手,實現(xiàn)自動化文件傳輸,以及如何根據(jù)需求進行擴展,例如增加錯誤處理、日志記錄和多線程支持。
1. ftplib庫介紹
1.1 FTP協(xié)議簡介
FTP(File Transfer Protocol)是一種用于在網(wǎng)絡(luò)上進行文件傳輸?shù)膮f(xié)議,它允許用戶從一臺計算機上傳文件到另一臺計算機,并從另一臺計算機下載文件。FTP使用兩個端口:21用于命令傳輸,20用于數(shù)據(jù)傳輸。它通過客戶端-服務(wù)器模型進行工作,其中用戶通過FTP客戶端軟件與FTP服務(wù)器進行交互。
1.2 ftplib庫的作用
ftplib是Python的內(nèi)置標(biāo)準(zhǔn)庫,它封裝了FTP協(xié)議的許多細(xì)節(jié),允許用戶通過簡單的接口來執(zhí)行FTP操作。使用ftplib,開發(fā)者可以不必深入了解FTP協(xié)議的復(fù)雜性,就能夠?qū)崿F(xiàn)文件的上傳和下載、目錄的瀏覽以及其他FTP服務(wù)器交互功能。
1.3 ftplib的主要功能模塊
ftplib庫主要由幾個類組成,其中最重要的包括 FTP 類,用于創(chuàng)建與FTP服務(wù)器的連接并進行登錄; FTPS 類,提供了加密連接(使用SSL/TLS)的支持;以及 error_reply 等異常處理類。這些類和方法構(gòu)成了ftplib的核心,使得Python程序員能夠方便地實現(xiàn)FTP客戶端功能。
通過本章的學(xué)習(xí),我們將奠定ftplib庫操作的基礎(chǔ),并為進一步深入探討如何使用這一庫進行高效地文件傳輸打下堅實的基礎(chǔ)。在下一章,我們將深入探討如何使用ftplib進行FTP連接與登錄。
2. FTP連接與登錄
連接FTP服務(wù)器
要使用ftplib庫連接FTP服務(wù)器,需要先導(dǎo)入該庫并創(chuàng)建一個FTP對象,然后使用這個對象的 connect 方法指定FTP服務(wù)器的地址、端口號(默認(rèn)是21)。代碼示例如下:
import ftplib
ftp = ftplib.FTP() # 創(chuàng)建FTP對象
ftp.connect('ftp.example.com') # 連接到FTP服務(wù)器連接參數(shù)分析
FTP():創(chuàng)建一個FTP對象實例,代表與FTP服務(wù)器的連接。connect():用于建立連接到FTP服務(wù)器。- 參數(shù)1 (
host): FTP服務(wù)器的主機名或IP地址。 - 參數(shù)2 (
port): FTP服務(wù)器監(jiān)聽的端口,默認(rèn)是21。
連接成功后,可以使用 print(ftp.getwelcome()) 來檢查是否連接成功,并打印出歡迎消息。
網(wǎng)絡(luò)異常處理
在實際應(yīng)用中,網(wǎng)絡(luò)問題可能會導(dǎo)致連接失敗。為此,需要對連接過程進行異常處理,確保程序的健壯性。代碼示例如下:
try:
ftp.connect('ftp.example.com', port=21)
except ftplib.error_perm as e:
print('連接失敗:', e)這里使用 try-except 語句捕獲 ftplib 可能拋出的異常,從而處理網(wǎng)絡(luò)連接異常。
用戶登錄
連接成功后,下一步通常是登錄到FTP服務(wù)器。可以使用FTP對象的 login 方法來進行用戶登錄,同時需要提供用戶名和密碼。代碼示例如下:
ftp.login('username', 'password') # 用戶登錄
登錄參數(shù)分析
login():用于登錄到FTP服務(wù)器。- 參數(shù)1 (
user): 用戶名。 - 參數(shù)2 (
passwd): 密碼。
同樣地,登錄過程也可能出現(xiàn)異常(如用戶名或密碼錯誤),因此需要進行異常處理:
try:
ftp.login('username', 'password')
except ftplib.error_perm as e:
print('登錄失敗:', e)權(quán)限驗證失敗的解決方法
若登錄失敗,通常是由于權(quán)限驗證問題。首先確認(rèn)提供的用戶名和密碼是否正確,然后檢查FTP服務(wù)器是否配置正確,以及是否允許匿名登錄(如果使用的是匿名賬號)。如果問題依舊,可能需要聯(lián)系服務(wù)器管理員進行進一步的排查。
代碼層面的深入
使用ftplib接口實現(xiàn)有效通信
ftplib庫提供了豐富的接口用于與FTP服務(wù)器進行交互。以下是一些常用的接口及其用途:
nlst(): 列出FTP服務(wù)器上的目錄內(nèi)容。cwd(): 更改當(dāng)前工作目錄。size(): 獲取指定文件的大小。delete(): 刪除指定文件。
這些接口通過FTP對象調(diào)用,例如 ftp.nlst() 會列出當(dāng)前目錄下的文件列表。
實現(xiàn)與FTP服務(wù)器的有效通信代碼示例
以下是通過ftplib接口實現(xiàn)與FTP服務(wù)器有效通信的代碼示例:
# 列出當(dāng)前目錄下的文件列表
try:
files = ftp.nlst()
for f in files:
print(f)
except ftplib.error_perm as e:
print('列出文件失敗:', e)
# 更改工作目錄
try:
ftp.cwd('target_directory')
except ftplib.error_perm as e:
print('更改工作目錄失敗:', e)
# 獲取文件大小
try:
file_size = ftp.size('somefile.txt')
print(f'文件somefile.txt的大小是 {file_size} 字節(jié)')
except ftplib.error_perm as e:
print('獲取文件大小失敗:', e)
# 刪除文件
try:
ftp.delete('file_to_delete.txt')
except ftplib.error_perm as e:
print('刪除文件失敗:', e)在這些操作中,異常處理是不可或缺的,它能幫助我們更好地理解錯誤發(fā)生的原因,并作出相應(yīng)的處理。
在下一節(jié)中,我們將探討如何通過ftplib庫實現(xiàn)文件上傳功能,深入到更加復(fù)雜的應(yīng)用場景中。
3. 文件上傳函數(shù)實現(xiàn)
文件上傳關(guān)鍵函數(shù)介紹
FTP協(xié)議支持文件的上傳操作,主要的上傳方式有兩種: storbinary 和 storlines 。 storbinary 用于二進制文件的上傳,而 storlines 適合文本文件的上傳。在ftplib庫中,這兩種方法都被封裝起來,使開發(fā)者能夠更容易地實現(xiàn)文件的上傳操作。
storbinary 函數(shù)
storbinary 函數(shù)接受一個命令字符串和一個可迭代的文件對象,它會逐步地從文件對象中讀取數(shù)據(jù)塊并上傳。使用 storbinary 時,需要提供一個格式化的命令字符串,通常為 "STOR filename" ,其中 filename 是服務(wù)器上對應(yīng)的文件名。
storlines 函數(shù)
storlines 函數(shù)適用于上傳文本文件,其使用方法與 storbinary 類似,但是它不處理文件對象中的二進制數(shù)據(jù),而是直接將文本行上傳到服務(wù)器。
接下來的章節(jié)將通過示例代碼來演示如何在實際應(yīng)用中使用這兩個函數(shù)。
實例代碼展示
使用 storbinary 上傳文件
from ftplib import FTP
def upload_file_binary(ftp, local_path, remote_path):
with open(local_path, 'rb') as fp:
ftp.storbinary(f'STOR {remote_path}', fp)在上面的示例中, upload_file_binary 函數(shù)接收FTP連接對象 ftp 、本地文件路徑 local_path 以及遠程服務(wù)器上的文件路徑 remote_path 作為參數(shù)。函數(shù)通過 with 語句以二進制模式打開本地文件,并調(diào)用 storbinary 方法上傳文件。
使用 storlines 上傳文本文件
def upload_file_text(ftp, local_path, remote_path):
with open(local_path, 'r') as fp:
ftp.storlines(f'STOR {remote_path}', fp)這個函數(shù)與 upload_file_binary 類似,但是它是以文本模式打開本地文件,并使用 storlines 方法來上傳。這種上傳方式適用于上傳純文本文件。
文件上傳常見錯誤處理
文件不存在錯誤
如果在嘗試上傳文件之前未正確檢查文件是否存在,將導(dǎo)致 FileNotFoundError 異常。為了避免這種情況,應(yīng)該在上傳前添加檢查文件存在的代碼:
import os
def check_file_exists(file_path):
if not os.path.exists(file_path):
raise FileNotFoundError(f"The file {file_path} does not exist.")上傳中斷錯誤
上傳過程中可能會遇到網(wǎng)絡(luò)波動導(dǎo)致上傳中斷??梢酝ㄟ^捕獲異常和重試機制來處理這種問題:
def try_upload(max_attempts=3):
attempts = 0
while attempts < max_attempts:
try:
upload_file_binary(ftp, local_path, remote_path)
break
except Exception as e:
attempts += 1
print(f"Upload failed: {e}. Retrying ({attempts}/{max_attempts})")
if attempts == max_attempts:
print("Max attempts reached. Upload failed.")這段代碼將嘗試最多 max_attempts 次上傳文件,如果在每次嘗試中發(fā)生異常,則會打印錯誤信息并重試,直到成功或達到最大嘗試次數(shù)。
完整文件上傳函數(shù)實現(xiàn)
class FTPUploader:
def __init__(self, ftp):
self.ftp = ftp
def upload(self, local_path, remote_path):
try:
self.check_file_exists(local_path)
with open(local_path, 'rb') as fp:
self.ftp.storbinary(f'STOR {remote_path}', fp)
except Exception as e:
print(f"Error occurred: {e}")
def check_file_exists(self, file_path):
if not os.path.exists(file_path):
raise FileNotFoundError(f"The file {file_path} does not exist.")以上是一個完整的 FTPUploader 類,其中包含了校驗文件是否存在以及上傳文件的方法。該類實例化后,只需要提供FTP連接實例,然后調(diào)用 upload 方法即可執(zhí)行文件上傳操作。
錯誤處理與日志記錄
在實現(xiàn)文件上傳功能的過程中,應(yīng)當(dāng)添加適當(dāng)?shù)腻e誤處理和日志記錄,以便于追蹤上傳過程中的異常和狀態(tài)信息。在Python中,可以通過內(nèi)置的 logging 模塊來實現(xiàn)日志記錄功能。
設(shè)置日志記錄
import logging
def setup_logging():
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')這段代碼將配置日志記錄器,使用INFO級別以及提供時間戳、日志級別和消息的格式。這樣可以在控制臺或文件中記錄日志信息。
在上傳函數(shù)中使用日志記錄
def upload(self, local_path, remote_path):
self.check_file_exists(local_path)
try:
with open(local_path, 'rb') as fp:
self.ftp.storbinary(f'STOR {remote_path}', fp)
logging.info(f"File {local_path} uploaded to {remote_path}")
except Exception as e:
logging.error(f"Upload failed: {e}")在文件上傳時,如果上傳成功,會記錄一條INFO級別的日志;如果出現(xiàn)異常,則記錄一條ERROR級別的日志。這樣可以在文件上傳過程中實時監(jiān)控狀態(tài)并記錄下發(fā)生的任何問題。
通過上述章節(jié),我們不僅學(xué)習(xí)了如何使用ftplib庫來實現(xiàn)文件的上傳功能,還了解了在上傳過程中可能出現(xiàn)的錯誤和如何進行有效處理,同時介紹了如何將日志記錄與錯誤處理集成到文件上傳操作中。這些知識點能夠幫助開發(fā)者編寫出既健壯又可靠的文件上傳腳本。
4. 文件下載函數(shù)實現(xiàn)
文件傳輸是網(wǎng)絡(luò)通信中的一個重要組成部分,而FTP作為文件傳輸?shù)闹匾獏f(xié)議之一,在進行文件下載時,擁有諸多便利性和高效性。在本章節(jié)中,我們將詳細(xì)介紹使用Python的ftplib庫實現(xiàn)文件下載的各個步驟,包括與下載相關(guān)的核心函數(shù)講解、具體的代碼示例以及錯誤處理與下載速度優(yōu)化策略。
關(guān)鍵函數(shù)與方法
實現(xiàn)文件下載功能,首先要熟悉ftplib庫中與下載相關(guān)的函數(shù)。 retrbinary 方法用于以二進制模式下載文件,而 retrlines 方法則以文本模式下載。 FTP.nlst 和 FTP.dir 等函數(shù)可以列出FTP服務(wù)器上的文件列表。
retrbinary函數(shù)
retrbinary 函數(shù)的使用格式如下:
def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
cmd: 發(fā)送到服務(wù)器的命令,用于請求文件,例如RETR filename。callback: 數(shù)據(jù)塊回調(diào)函數(shù),通常使用StringIO或者BytesIO對象來保存下載數(shù)據(jù)。blocksize: 數(shù)據(jù)塊的大小。rest: 從文件的哪個位置開始下載,常用于斷點續(xù)傳。
retrlines函數(shù)
retrlines 函數(shù)使用格式如下:
def retrlines(self, cmd, callback):
cmd: 同retrbinary。callback: 當(dāng)服務(wù)器發(fā)送一行數(shù)據(jù)時的回調(diào)函數(shù)。
示例代碼
下面是一個簡單的代碼示例,展示了如何使用 retrbinary 函數(shù)下載一個文本文件:
from ftplib import FTP
from io import BytesIO
def download_file(ftp, remote_file_path, local_file_path):
local_file = open(local_file_path, 'wb')
try:
ftp.retrbinary('RETR ' + remote_file_path, local_file.write)
except Exception as e:
print('下載過程中發(fā)生錯誤:', e)
finally:
local_file.close()
# 假設(shè)已成功連接FTP服務(wù)器并登錄
ftp = FTP('ftp.example.com')
ftp.login(user='username', passwd='password')
# 下載位于FTP服務(wù)器上的名為example.txt的文件
download_file(ftp, 'example.txt', 'example.txt')
ftp.quit()在上述代碼中,我們定義了 download_file 函數(shù),該函數(shù)接受FTP對象、遠程文件路徑和本地文件路徑作為參數(shù)。通過 retrbinary 方法,以二進制模式下載文件,并保存到本地路徑。同時,我們展示了錯誤處理的邏輯,確保在發(fā)生異常時關(guān)閉已打開的文件并打印錯誤信息。
文件下載實現(xiàn)
要實現(xiàn)一個完整的文件下載功能,需要考慮文件的獲取方式、保存位置、下載進度的顯示以及下載結(jié)束后對文件的處理。在實現(xiàn)下載功能時,應(yīng)先檢查本地文件是否存在,如果存在并且大小與遠程服務(wù)器上的文件相同,則可以跳過下載過程。
下載進度顯示
為了提高用戶體驗,我們可以將下載進度顯示出來。例如,在上面的 download_file 函數(shù)中,可以通過 BytesIO 對象記錄寫入的數(shù)據(jù)量來計算下載進度:
from io import BytesIO
def download_file(ftp, remote_file_path, local_file_path):
local_file = open(local_file_path, 'wb')
total_size = int(ftp.size(remote_file_path)) # 獲取遠程文件大小
progress = BytesIO()
try:
ftp.retrbinary('RETR ' + remote_file_path, progress.write)
progress.seek(0)
downloaded = len(progress.getbuffer()) # 已下載的數(shù)據(jù)量
print(f"下載進度: {downloaded}/{total_size} ({downloaded / total_size * 100:.2f}%)")
except Exception as e:
print('下載過程中發(fā)生錯誤:', e)
finally:
local_file.close()斷點續(xù)傳
斷點續(xù)傳是指在網(wǎng)絡(luò)下載中斷后,可以從上次中斷的地方重新開始下載,而不是重新下載整個文件。這可以大大提高下載效率,特別是在下載大文件時。通過 retrbinary 函數(shù)的 rest 參數(shù)可以實現(xiàn)斷點續(xù)傳:
def download_file_resumable(ftp, remote_file_path, local_file_path):
local_file = open(local_file_path, 'ab') # 以追加模式打開文件
progress = BytesIO()
try:
# 嘗試獲取本地文件大小,如果不存在則為0
local_file.seek(0, 2) # 移動到文件末尾
local_file_size = local_file.tell()
# 從服務(wù)器獲取文件大小
remote_file_size = int(ftp.size(remote_file_path))
# 計算需要下載的文件大小
size = remote_file_size - local_file_size
# 如果本地文件大小小于服務(wù)器文件大小,則從剩余部分開始下載
if local_file_size < remote_file_size:
ftp.retrbinary('RETR ' + remote_file_path, progress.write, rest=local_file_size)
local_file.write(progress.getvalue())
downloaded = local_file_size + len(progress.getbuffer())
print(f"下載進度: {downloaded}/{remote_file_size} ({downloaded / remote_file_size * 100:.2f}%)")
else:
print("本地文件已完整下載。")
except Exception as e:
print('下載過程中發(fā)生錯誤:', e)
finally:
local_file.close()下載速度優(yōu)化與文件完整性驗證
下載速度是用戶體驗的重要組成部分,尤其是對于大文件下載。為了優(yōu)化下載速度,可以嘗試增加數(shù)據(jù)塊的大?。?nbsp;blocksize 參數(shù))。但是,要根據(jù)網(wǎng)絡(luò)條件合理設(shè)置,避免過大而導(dǎo)致服務(wù)器壓力過高或網(wǎng)絡(luò)擁塞。
下載速度優(yōu)化
增加數(shù)據(jù)塊大小可以通過減少與FTP服務(wù)器交互次數(shù)來提升速度。但是,過大的數(shù)據(jù)塊可能會導(dǎo)致緩沖區(qū)溢出或網(wǎng)絡(luò)延遲問題。因此,在優(yōu)化下載速度時,需要進行多次嘗試,找到最優(yōu)的數(shù)據(jù)塊大小。
def download_file_optimized(ftp, remote_file_path, local_file_path):
local_file = open(local_file_path, 'wb')
try:
ftp.retrbinary('RETR ' + remote_file_path, local_file.write, blocksize=16384) # 設(shè)置更大的塊大小
except Exception as e:
print('下載過程中發(fā)生錯誤:', e)
finally:
local_file.close()文件完整性驗證
為了保證下載的文件是完整且未被篡改的,我們需要對下載的文件進行完整性驗證。通常采用MD5或SHA1等散列算法對文件進行校驗。
import hashlib
def verify_file_integrity(local_file_path, expected_md5):
hash_md5 = hashlib.md5()
with open(local_file_path, 'rb') as file:
for chunk in iter(lambda: file.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest() == expected_md5
# 使用示例
expected_md5 = 'your_expected_md5_value' # 需要提前獲取
if verify_file_integrity('example.txt', expected_md5):
print("文件完整性驗證成功。")
else:
print("文件完整性驗證失敗。")小結(jié)
在本章節(jié)中,我們深入學(xué)習(xí)了使用ftplib庫實現(xiàn)文件下載功能的相關(guān)知識點。我們首先介紹了關(guān)鍵的下載函數(shù)和方法,然后通過具體的代碼示例展示了如何編寫一個可靠的文件下載函數(shù)。在此基礎(chǔ)上,我們討論了下載進度顯示、斷點續(xù)傳、速度優(yōu)化以及文件完整性驗證的重要性與實現(xiàn)方法。
通過以上內(nèi)容,讀者應(yīng)當(dāng)能夠掌握如何使用Python進行高效、穩(wěn)定、安全的文件下載操作。在接下來的章節(jié)中,我們將進一步了解如何將文件上傳和下載功能集成到自動化腳本中,并實現(xiàn)復(fù)雜的自動化文件傳輸任務(wù)。
5. 自動化文件傳輸腳本編寫
5.1 自動化腳本設(shè)計思路
設(shè)計自動化文件傳輸腳本時,首先要明確腳本的主要任務(wù)和目標(biāo)環(huán)境。這包括確定需要上傳和下載的文件類型,以及FTP服務(wù)器的相關(guān)信息,如地址、端口、用戶名、密碼等。接著規(guī)劃腳本的執(zhí)行流程,包括初始化連接、文件操作(上傳、下載)、斷開連接等,并且為腳本添加必要的異常處理機制以提高其健壯性。
5.2 實現(xiàn)步驟與代碼示例
步驟一:連接FTP服務(wù)器
使用ftplib庫的FTP類來建立與服務(wù)器的連接。如果連接成功,登錄到服務(wù)器;失敗則拋出異常,并做異常處理。
import ftplib
def connect_ftp(server, username, password):
ftp = ftplib.FTP(server)
try:
ftp.login(username, password)
print("成功連接并登錄到FTP服務(wù)器。")
except Exception as e:
print(f"連接或登錄失敗:{e}")
return ftp步驟二:文件上傳與下載
編寫文件上傳與下載函數(shù),分別利用 storbinary 和 retrbinary 方法進行操作。
def upload_file(ftp, local_file_path, remote_file_path):
with open(local_file_path, 'rb') as file:
ftp.storbinary(f'STOR {remote_file_path}', file)
print(f"文件 {local_file_path} 已上傳至 {remote_file_path}")
def download_file(ftp, remote_file_path, local_file_path):
with open(local_file_path, 'wb') as file:
ftp.retrbinary(f'RETR {remote_file_path}', file.write)
print(f"文件 {remote_file_path} 已下載至 {local_file_path}")步驟三:任務(wù)調(diào)度與多線程
為了提高效率,可以使用Python的 threading 模塊來實現(xiàn)多線程操作,同時使用 schedule 模塊來設(shè)置定時任務(wù)。
import threading
import schedule
def schedule_file_transfer():
# 這里可以定義定時任務(wù)的規(guī)則和時間
schedule.every().day.at("10:00").do(upload_and_download_files)
def upload_and_download_files():
ftp = connect_ftp('ftp.example.com', 'username', 'password')
if ftp:
upload_file(ftp, 'path/to/local/file', 'path/to/remote/file')
download_file(ftp, 'path/to/remote/file', 'path/to/local/file')
ftp.quit() # 關(guān)閉連接步驟四:日志記錄
記錄腳本運行過程中的關(guān)鍵信息,以便于后續(xù)分析和排錯。
import logging
def setup_logging():
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s')
return logging.getLogger()
def log_transfer_info(logger, message):
logger.info(f"文件傳輸信息: {message}")
# 在文件上傳和下載函數(shù)中調(diào)用 log_transfer_info 來記錄日志步驟五:集成與測試
將上述步驟集成到一個腳本文件中,并進行充分的測試,確保腳本按照預(yù)期工作。
if __name__ == '__main__':
logger = setup_logging()
schedule_file_transfer()
while True:
schedule.run_pending()
# 這里可以添加其他任務(wù)或讓程序休眠一段時間5.3 實際案例分析
通過一個實際案例來演示自動化文件傳輸腳本的具體應(yīng)用場景。比如,假設(shè)需要每日定時將本地數(shù)據(jù)庫的備份文件上傳到FTP服務(wù)器,并從服務(wù)器下載最新的配置文件到本地。
5.4 錯誤處理與優(yōu)化建議
在腳本的測試和使用過程中,要注意記錄和分析可能發(fā)生的異常,及時優(yōu)化腳本。例如,可以優(yōu)化網(wǎng)絡(luò)延遲和斷線重連的策略,提高文件傳輸?shù)姆€(wěn)定性和可靠性。
通過以上步驟,我們可以構(gòu)建一個基礎(chǔ)的自動化文件傳輸腳本。在實際運用中,還需要根據(jù)具體需求進行調(diào)整和優(yōu)化。
以上就是Python編寫FTP自動化上傳下載腳本的實現(xiàn)指南的詳細(xì)內(nèi)容,更多關(guān)于Python FTP自動化上傳下載的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python的網(wǎng)絡(luò)編程庫Gevent的安裝及使用技巧
Gevent庫的奧義在于并發(fā)式的高性能網(wǎng)絡(luò)程序設(shè)計支持,這里我們將來講解Python的網(wǎng)絡(luò)編程庫Gevent的安裝及使用技巧,來看一下Gevent支持的多進程程序編寫:2016-06-06

