Python で SFTP 機能を作成する
Secure Socket Shell (SSH) は、別のコンピューターにアクセスできるようにする安全で優れたネットワーク プロトコルであり、SHA と暗号化によるパスワードと公開キー認証を使用します。
SSH ファイル転送プロトコル (SFTP) は、SSH を使用するファイル転送プロトコルであり、以前に使用されていた一般的な FTP よりも優れています。
Python でアプリケーションを開発するには、ファイル転送プロトコルが必要になる場合があります。 パスワード スニッフィングや中間者攻撃などの攻撃を克服し、データの整合性を維持するデフォルトの機能を提供する SFTP を使用する必要があります。
この記事では、Python 内で SFTP を使用してデータとファイルを移動する方法について説明します。
pysftp
を使用して Python で SFTP 機能を作成する
Python には、セキュアでない FTP プロトコル サービスを提供するヘルパー関数を備えた FTP クライアント クラスである ftplib
が付属しています。 SFTP を使用するには、サードパーティのライブラリをインストールする必要があります。そのようなライブラリの 1つが pysftp
ライブラリです。
pysftp
を使用すると、SFTP にアクセスし、安全なプロトコルを使用してアプリケーションのニーズを満たすことができます。 pysftp
をインストールするには、pip
を使用する必要があります。
pip install pysftp
また、SFTP サーバーも必要です。 Windows の場合、WinSCP
ソフトウェアを使用します。ただし、SFTP サーバーがある場合は、始めましょう。
コードを書く前に、private key
と username
(akinl
) およびホスト名 (localhost
) を使用して SFTP サーバーにログインします。
これで、root
フォルダーにログインしました。 私たちの目標は、root
ディレクトリ内に存在するファイルとディレクトリを一覧表示し、ファイルを SFTP
サーバー、特に store
ディレクトリにコピーすることです。
pysftp
ライブラリで指定された定義済みのコード テンプレートを使用してコーディングを開始しましょう。 コード内で、hostname
、port
、username
、および private key path
を割り当てました。
これらの値は SFTP サーバーの詳細から通知され、秘密鍵
は Python ファイルのディレクトリにコピーされます。
import pysftp
sftpHostName = "localhost"
sftpPort = 22
userName = "akinl"
privateKeyPath = "./id_rsa"
with pysftp.Connection(
host=sftpHostName,
port=sftpPort,
username=userName,
private_key=privateKeyPath,
cnopts=cnOptions,
) as sftp:
print("Connected to SFTP server!")
上記のコードは、指定されたパラメーターで SFTP 接続オブジェクト (pysftp.Connection()
) を使用して SFTP サーバーに接続します。 with
ブロック内では、sftp
という名前のオブジェクト内で確立された SFTP 接続があります。
以下は、コードの出力です。
C:\\Python310\\lib\\site-packages\\pysftp\\__init__.py:61: UserWarning: Failed to load HostKeys from C:\\Users\\akinl\\.ssh\\known_hosts. You will need to explicitly load HostKeys (cnopts.hostkeys.load(filename)) or disableHostKey checking (cnopts.hostkeys = None).
warnings.warn(wmsg, UserWarning)
Traceback (most recent call last):
File "c:\\Users\\akinl\\Documents\\Python\\SFTP\\index.py", line 8, in <module>
with pysftp.Connection(host=sftpHostName, port=sftpPort, username=userName, private_key=privateKeyPath) as sftp:
File "C:\\Python310\\lib\\site-packages\\pysftp\\__init__.py", line 132, in __init__
self._tconnect['hostkey'] = self._cnopts.get_hostkey(host)
File "C:\\Python310\\lib\\site-packages\\pysftp\\__init__.py", line 71, in get_hostkey
raise SSHException("No hostkey for host %s found." % host)
paramiko.ssh_exception.SSHException: No hostkey for host localhost found.
Exception ignored in: <function Connection.__del__ at 0x000001F0E9656320>
Traceback (most recent call last):
File "C:\\Python310\\lib\\site-packages\\pysftp\\__init__.py", line 1013, in __del__
self.close()
File "C:\\Python310\\lib\\site-packages\\pysftp\\__init__.py", line 784, in close
if self._sftp_live:
AttributeError: 'Connection' object has no attribute '_sftp_live'
ホスト %s のホストキーが見つかりません
は、ホスト ファイルが存在しない場合に発生する、pysftp
で SFTP 接続オブジェクトを操作する際の一般的なエラーです。
この問題を処理するには、接続オプション (pysftp.CnOpts()
) を作成し、ホスト キーが None
であることを指定して、既知のホスト チェックを無視します。
import pysftp
sftpHostName = "localhost"
sftpPort = 22
userName = "akinl"
privateKeyPath = "./id_rsa"
cnOptions = pysftp.CnOpts()
cnOptions.hostkeys = None
with pysftp.Connection(
host=sftpHostName,
port=sftpPort,
username=userName,
private_key=privateKeyPath,
cnopts=cnOptions,
) as sftp:
print("SFTP server connection successful")
コードの出力は次のとおりです。
C:\Python310\lib\site-packages\pysftp\__init__.py:61: UserWarning: Failed to load HostKeys from C:\Users\akinl\.ssh\known_hosts. You will need to explicitly load HostKeys (cnopts.hostkeys.load(filename)) or disableHostKey checking (cnopts.hostkeys = None).
warnings.warn(wmsg, UserWarning)
SFTP server connection successful
唯一のエラーは、無効化されたホスト キー チェックに関する低レベルの警告です。 まず、作業ディレクトリを変更して、SFTP サーバー内にいることを示しましょう。
import pysftp
sftpHostName = "localhost"
sftpPort = 22
userName = "akinl"
privateKeyPath = "./id_rsa"
cnOptions = pysftp.CnOpts()
cnOptions.hostkeys = None
with pysftp.Connection(
host=sftpHostName,
port=sftpPort,
username=userName,
private_key=privateKeyPath,
cnopts=cnOptions,
) as sftp:
print("SFTP server connection successful")
print("The current working directory is ", sftp.pwd)
sftp.cwd("./store")
print("After the cwd operation, the current working directory is ", sftp.pwd)
上記のコードの出力を以下に示します。
SFTP server connection successful
The current working directory is /
After the cwd operation, the current working directory is /store.
cwd
は、現在の作業ディレクトリをその引数として指定されたものに変更します。 また、listdir()
メソッドを使用して root
および store
ディレクトリ内のファイルを一覧表示することもできます。
import pysftp
sftpHostName = "localhost"
sftpPort = 22
userName = "akinl"
privateKeyPath = "./id_rsa"
cnOptions = pysftp.CnOpts()
cnOptions.hostkeys = None
with pysftp.Connection(
host=sftpHostName,
port=sftpPort,
username=userName,
private_key=privateKeyPath,
cnopts=cnOptions,
) as sftp:
rootFiles = sftp.listdir()
storeFiles = sftp.listdir("./store")
print(rootFiles, storeFiles)
コードの出力は次のとおりです。
['index.txt', 'main.py', 'store'] []
listdir()
メソッドは、引数が渡されない場合、現在の作業ディレクトリ内のすべてのファイルとディレクトリを一覧表示しますが、引数を指定すると、渡した引数内のファイルをチェックします。 その結果、ファイルが存在しないため、root
ディレクトリには 2つのファイルと 1つのディレクトリがあり、store
ディレクトリには何もありませんでした。
それでは、put()
、put_d()
、および put_r()
メソッドを使用して、いくつかのファイルを SFTP サーバーに移動してみましょう。 put()
を使用して、ファイルのみを移動します。
次に、python ファイルと同じディレクトリ内に test.txt
という名前のテキスト ファイルを作成し、そのファイルを SFTP サーバーにコピーします。
import pysftp
sftpHostName = "localhost"
sftpPort = 22
userName = "akinl"
privateKeyPath = "./id_rsa"
cnOptions = pysftp.CnOpts()
cnOptions.hostkeys = None
with pysftp.Connection(
host=sftpHostName,
port=sftpPort,
username=userName,
private_key=privateKeyPath,
cnopts=cnOptions,
) as sftp:
sftp.put("test.txt", preserve_mtime=True)
コードの出力:
test.txt
ファイルは現在、SFTP サーバーのルート ディレクトリにあります。 次に、同じ test.txt
を store
ディレクトリに移動し、コピー前とコピー後のファイルの内容を一覧表示します。
import pysftp
sftpHostName = "localhost"
sftpPort = 22
userName = "akinl"
privateKeyPath = "./id_rsa"
cnOptions = pysftp.CnOpts()
cnOptions.hostkeys = None
with pysftp.Connection(
host=sftpHostName,
port=sftpPort,
username=userName,
private_key=privateKeyPath,
cnopts=cnOptions,
) as sftp:
print(sftp.listdir("./store"))
sftp.put("test.txt", preserve_mtime=True, remotepath="./store/upload.txt")
print(sftp.listdir("./store"))
上記のコードの出力は、test.txt
ファイルが upload.txt
としてサーバーにアップロードされ、画像内に表示されていることを示しています。
[]
['upload.txt']
put_d()
メソッドを使用して、ディレクトリの内容をコピーできます。 たとえば、3つのテキスト ファイル (one.txt
、two.txt
、および three.txt
) を含む SeptData
ディレクトリを作成し、ディレクトリの内容を root
フォルダーにコピーしてみましょう。
ただし、コピー元のパスには、以前に使用した相対パスではなく、完全パスが必要です。
import pysftp
sftpHostName = "localhost"
sftpPort = 22
userName = "akinl"
privateKeyPath = "./id_rsa"
cnOptions = pysftp.CnOpts()
cnOptions.hostkeys = None
with pysftp.Connection(
host=sftpHostName,
port=sftpPort,
username=userName,
private_key=privateKeyPath,
cnopts=cnOptions,
) as sftp:
print(sftp.listdir("./"))
sftp.put_d(
r"C:\Users\akinl\Documents\Python\SFTP\SeptData", "./", preserve_mtime=True
)
print(sftp.listdir("./"))
コードの出力:
['index.txt', 'main.py', 'store', 'test.txt']
['index.txt', 'main.py', 'one.txt', 'store', 'test.txt', 'three.txt', 'two.txt']
3つのファイルは、ディレクトリ内のファイルとディレクトリのリストで表されるように、root
ディレクトリ内に存在します。 したがって、get()
メソッドを使用して SFTP サーバーからファイルをダウンロードできます。
import pysftp
sftpHostName = "localhost"
sftpPort = 22
userName = "akinl"
privateKeyPath = "./id_rsa"
cnOptions = pysftp.CnOpts()
cnOptions.hostkeys = None
with pysftp.Connection(
host=sftpHostName,
port=sftpPort,
username=userName,
private_key=privateKeyPath,
cnopts=cnOptions,
) as sftp:
sftp.get("./store/upload.txt", preserve_mtime=True)
コードが正常に実行されると、upload.txt
ファイルが python ファイルのディレクトリ内に存在します。 get_d()
および get_r()
メソッドを使用して、リモート ディレクトリを取得できます。
paramiko
を使用して Python で SFTP 機能を作成する
Paramiko は、クラスとメソッドを介して Python 用の SSHv2
を簡単に実装できる優れたライブラリです。 これらの方法のいくつかを使用して、SFTP サーバーへの接続を開始し、公開鍵
認証を介してそのサーバーと連携できます。
paramiko
をインストールするには、次のように pip
コマンドを使用できます。
pip install paramiko
前のセクションの接続の詳細を使用して、作業ディレクトリの変更からリモート SFTP サーバーからのファイルの取得まで、同じ操作を実行できます。
SSHClient()
は、SFTP サーバーに接続するための新しい SSH を作成し、set_missing_host_key_policy()
は、既知のホスト キーなしでサーバーに接続するためのポリシーを設定できるようにし、connect()
メソッドを使用します。 SFTP サーバーへの実際の接続を作成します。
ディレクトリを store
ディレクトリに変更し、現在の作業ディレクトリとそのディレクトリの内容を、それぞれ chdir
、getcwd
、および listdir
を使用して出力します。
import paramiko
sftpHostName = "localhost"
sftpPort = 22
userName = "akinl"
privateKeyPath = "./id_rsa"
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(
hostname=sftpHostName, port=sftpPort, username=userName, key_filename=privateKeyPath
)
sftp_client = ssh.open_sftp()
sftp_client.chdir("./store")
print(sftp_client.getcwd())
print(sftp_client.listdir())
sftp_client.close()
ssh.close()
コードの出力:
/store
['one.txt', 'three.txt', 'two.txt', 'upload.txt']
最初の行には、chdir()
メソッドによって設定された現在の作業ディレクトリが含まれており、2 行目には、store
ディレクトリ内のファイルとディレクトリのリストが含まれています。
Olorunfemi is a lover of technology and computers. In addition, I write technology and coding content for developers and hobbyists. When not working, I learn to design, among other things.
LinkedIn