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

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

新規登録して質問してみよう
ただいま回答率
85.48%
ファイル

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

Python

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

Q&A

1回答

11418閲覧

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

airi_pumpkin

総合スコア30

ファイル

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

Python

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

0グッド

0クリップ

投稿2017/09/28 15:51

まず、大元のフォルダにアクセスし、その中にある複数あるフォルダの中の画像ファイル名を変え、
終わったら次のフォルダの中の画像ファイル名を変える。
ということをしたいのですが、「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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LouiS0616

2017/09/28 16:09

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

退会済みユーザー

2017/09/28 22:24

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

2017/09/29 10:16

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

回答1

0

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

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

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

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デバッグといいます)

python

1from pprint import pprint 2 3photo = dir_path[count] + image[count] + '/' 4pprint('元のパスは:' + photo) # ←これ

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


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

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

python

1"""before""" 2for y in range(len(dir_path)): 3 image = os.listdir(top_dire + dir_path[y]) 4 5"""after""" 6for sub_dir in dir_path: 7 image = os.listdir(top_dire + sub_dir)

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

python

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

投稿2017/09/29 03:04

編集2017/09/29 03:33
miyahan

総合スコア3095

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

airi_pumpkin

2017/09/29 10:19

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

退会済みユーザー

2017/09/29 10:40

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問