質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.34%

  • Python

    9190questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • FTP

    333questions

    FTP(File Transfer Protocol)は、ネットワークでのファイル転送を行うための通信プロトコルの1つである。

  • 文字コード

    214questions

    文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

Python でFTP領域のファイル一覧リストの日本語表示

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 567

M25605301621

score 1

 ftpのファイル一覧リストの日本語表示

ftp内のファイル一覧を手軽に取得できるツールを作ろうとしているのですが、
日本語を含むファイル名の取得結果が文字化けしてしまいます。

取得した文字列をencode('shift-JIS')やencode('UTF-8')かけてみると、
エラーメッセージが表示されます。
なんとかファイルの日本語名までprintできないものでしょうか。
どうかご教示ください。

 発生している問題・エラーメッセージ

UnicodeEncodeError
'euc-jp' codec can't encode charavtor '/x91' in position 6: ille...
('shift-JIS'も同様)

 該当のソースコード

from ftplib import FTP
_myFtp =FTP('address','user','pass')
items = _myFtp.nlst('dir1/dir2/dir3/dir4/')
for row in items :
    print(row.encode('euc-jp'))    
print('end')
_myFtp.quit()

 試したこと

row.replace('x91','')
↑エラーに変化なし

 補足情報(FW/ツールのバージョンなど)

Pythonistaを使用しています。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • KSwordOfHaste

    2018/05/30 14:13

    rowの型はなんでしょう?つまりprint(type(row))とやると何が表示されますか?

    キャンセル

  • M25605301621

    2018/05/30 15:08

    <class 'str'>と返ってきました!といいますか、型確認の方法自体知りませんでした。ありがとうございます。

    キャンセル

回答 1

checkベストアンサー

+2

そもそもFTPにおいて日本語を含むファイル名を使うのは避けるべきなのですが…

ftplibソースのこのあたりこのあたりを見るからに、.nlstの結果をLatin-1( ISO-8859-1)として読み込んでいるのが問題のようです。
サーバの返すテキストのエンコーディングと、読込用に開いているテキストのエンコーディングが正しくマッチしていない場合、読込後の文字列(str型)の内容が正しくなりません。

そこでFTPサーバの返す文字列のエンコーディングを事前に確認しておき、ソース上で明示的に指定することで正しく動作する可能性があります。

参考:Python: Reading Ftp file list with UTF-8?

 修正

サーバ側が対応しているかによりますが、OPTS UTF8 ONコマンドによって、サーバ応答をUTF-8エンコーディング指定できるかもしれません。指定できた場合はftp.encoding = 'utf-8'によりutf-8で受け取れます。

以下、検証コードです。
当方環境のIIS(10.0)や、著名FTPサイトではこのコマンドに対応しているようです。

from ftplib import FTP, all_errors

host_names = [
    #'localhost', # 独自検証できるサーバがあれば…
    'ftp.riken.go.jp','ftp.jaist.ac.jp','ftp.u-aizu.ac.jp','ftp.iij.ad.jp','ftp.mirrorservice.org' # 著名サイト
    ]

with open( 'nlst.txt', 'w', encoding='utf-8') as f:

    for host_name in host_names:
        with FTP(host_name) as ftp:
            print(host_name)
            f.write(host_name + '\n')

            # まずはサーバ側にUTF-8で応答してもらうように頼む
            try:
                print(ftp.sendcmd('OPTS UTF8 ON')) # 確認用

                ftp.voidcmd( 'OPTS UTF8 ON')
                ftp.encoding = 'utf-8'
            except all_errors as e:
                print( e)
                # 'Latin-1'以外のサーバが利用している(と思われる)エンコーディングが分かっていれば指定する
                ftp.encoding = 'shift_jis'

            ftp.login()
            items = ftp.nlst('pub/')
            for row in items:
                f.write(row + '\n') # 標準出力に惑わされないようファイルにも出力
                print(row)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/30 15:10

    ご回答ありがとうございます。いただいた情報をもとに改修して、またコメント致します。

    キャンセル

  • 2018/05/30 16:21

    ↓ご指南いただいた1行で解決しました。
    ftp.encoding = 'shift_jis' # この行を追加
    取得したファイル名群ではなく、ftplibのインスタンス側にエンコーティングを指定することで
    うまく動作した、と理解しています。
    日本語ファイル名は確かに不適切と思います。このコードを発展させてツールとして機能できるよう試行してみます。ありがとうございました。

    キャンセル

  • 2018/05/30 16:27

    > ftplibのインスタンス側にエンコーティングを指定する
    はい。その理解で正しいです。
    なお「OPTS UTF8 ON」コマンドによる対処法について追記しました。
    サーバー側が対応しているかによりますが、UTF-8で受け取れると、後の処理が楽になります。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Python

    9190questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • FTP

    333questions

    FTP(File Transfer Protocol)は、ネットワークでのファイル転送を行うための通信プロトコルの1つである。

  • 文字コード

    214questions

    文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。