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

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

ただいまの
回答率

90.47%

  • Python

    8607questions

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

  • ファイル

    174questions

    ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

ファイル操作をしたいけど、エラーがわからず詰まっています...

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,362

Tio

score 21

まず、大元のフォルダにアクセスし、その中にある複数あるフォルダの中の画像ファイル名を変え、
終わったら次のフォルダの中の画像ファイル名を変える。
ということをしたいのですが、「jpg = len(image)」のところで
「 TypeError: object of type 'bool' has no len() 」
というエラーが出てきます。
調べても答えが見つからないのでご回答の程お願いします。

macOS 10.12.6
python 3.6.2

# -*- coding: utf8 -*-
import sys
import os
import shutil

top_dire  = './dir/'
dir_path = []

#大元フォルダの中にあるフォルダだけのパスを取得し、配列に加える
for x in os.listdir(top_dire):
    if os.path.isdir(top_dire + x):
        dir_path.append(x)

#中にあったフォルダの数回す
for y in range(len(dir_path)):
    image  = []
    count = 1
    j = 1
    i = 0
     
    image  = os.listdir(dir_path[y]) #画像ファイルを配列に加える
    jpg = len(image) #ここでエラー出現

    #画像ファイルの枚数分回す
    for i in range(jpg):
        photo = dir_path[count] + image[count] + '/'
        pic_path = photo
        count += 1

        path = os.path.splitext(pic_path) #名前と拡張子を分ける

        if j < 10:
            os.rename(pic_path, dir_path + '0' + '0' + j + path[1])
        elif j >= 10 and j <= 99:
            os.rename(pic_path, dir_path + '0' + j + path[1])
        else:
            os.rename(pic_path, dir_path + j + path[1])

        j += 1
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • LouiS0616

    2017/09/29 01:09

    これ、本当に実際のコードをコピペしたものですか?全角スペースが含まれているので、そもそもご提示のエラーまでたどり着かないように思うのですが。

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2017/09/29 07:24

    20行目位にある不正な文字を削ったのですが、全角スペースだったのですね。他にもcount=1をcount=0にしないと動かない、dir_pathはdir_path[count]にしないと動かない、最後の方のif j < 10のあたりはゼロパディングをすればもっとすっきりできる、までは分かりました。手元のデータではファイル名修正でこけているのでまだ呈示できませんが…

    キャンセル

  • Tio

    2017/09/29 19:16

    実際のコードはちゃんと全角とかはないのですが、ここで色々といじってしまっていたのでそのせいで全角スペースが含まれてしまったのかもしれません。本当に申し訳ないです

    キャンセル

回答 1

+5

全体的にバグが非常に多くどこから手を付けて良いかわからない状態です。。

横着してやりたいことを全部書いてから実行してみて出たエラーに慌てて対処するのではなく、処理をいくつかのステップに分けて少し作ってうまく動くか試して…少し作って…を繰り返しコツコツ開発していく習慣を身に付けた方がよいと思います。バグは開発が進めば進むほど原因特定・修正が難しくなります

参考までにざっと見で気づいたバグを述べます:

image = os.listdir(dir_path[y])

dir_path[y] というディレクトリは存在しません。

photo = dir_path[count] + image[count] + '/'

ファイルを取り出しているのになぜ / を付けてディレクトリ表記にしているんでしょう?また、そもそもそんなファイルは存在しません。そしてなぜキーが count ??

os.rename(pic_path, dir_path + j + path[1])

文字列(str)連結なのに dir_path はリスト(list)、 j は整数(int)なのはおかしいです。そしてもちろん、そんなファイルは存在しません。


TypeError: object of type 'bool' has no len() というメッセージは、bool型の image 変数に対し len() は実行できないと怒っています。

  • TypeError: can only concatenate list (not "str") to list
  • TypeError: must be str, not int

といった TypeError が出る主な原因はそもそも関数の使い方が間違っているか、自分が思っているのとは違う型の変数を渡してしまった場合です。

今回の場合、image はディレクトリの一覧を格納した list であるはずですが、なぜか bool になっています。すなわち原因は TypeError が起きた行ではなく、image に値を代入したところにあります。


というわけで、各所各所で変数や文字連結の結果が自分の想定通りになっているひたすらチェックしましょう。デバッガを使うとはかどりますが、そのセットアップが面倒であれば、print() で変数や連結した文字列を表示させて目で確認していきましょう。print の替わりに pprint を使うとより見やすく表示してくれます。(ちなみにこれをprintデバッグといいます)

from pprint import pprint

photo = dir_path[count] + image[count] + '/'
pprint('元のパスは:' + photo)  # ←これ

あとバグとは言い切れないものの考慮が甘い部分があります。各ディレクトリ内にフォルダや画像以外のファイル(OSが自動作成しているメタファイル)があった場合、意図しない動作をしてしまう恐れがあります。リネーム対象なのか(フォルダではなくファイルか、拡張子は画像(jpg, jpeg, gif, png...)なのか)をチェックする処理を入れた方がよいと思います。


最後に余談ですが、使っている変数名が i, j, y だと何に使っているカウンタなのかわかりませんし、image や photo も漠然としていて何を格納しているかわからないので、もう少し命名を工夫した方がよいと感じました。

また配列へキーを使ってアクセスしなくても for で変数に入れてしまえばすっきりします。

"""before"""
for y in range(len(dir_path)):
    image = os.listdir(top_dire + dir_path[y])

"""after"""
for sub_dir in dir_path:
    image = os.listdir(top_dire + sub_dir)

同時にキーも欲しい場合は enumerate() を使います:

for key, sub_dir in enumerate(dir_path):
    print('{}番目のディレクトリは {!r} です'.format(key, sub_dir))

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/29 19:19

    何から何までご丁寧に説明ありがとうございます。miyahanさんの意見を参考にして書き直してみようと思います。ご回答本当にありがとうございます。

    キャンセル

  • 2017/09/29 19:40

    何も知らずにいつもprintしていました。pprintすごいですね、参考になります。

    キャンセル

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

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

関連した質問

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

  • Python

    8607questions

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

  • ファイル

    174questions

    ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。