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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

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

Q&A

解決済

3回答

1472閲覧

複数作成したパスワードをファイル保存したいです。

KiX4Q

総合スコア1

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

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

0グッド

0クリップ

投稿2021/04/13 05:17

Pythonでパスワード生成ツールを作成しています。

作成したいパスワードの数を入力すると、その分のパスワードが作成されるというものです。
作成したパスワードをファイルに保存したいです。
複数作成するとprintの出力では指定した分全部表示されますが、ファイル保存した方はその一番最後のパスワード1つしか保存されません。

実際の画面

【パスワード作成数:3】の場合

<print出力>
イメージ説明
<ファイル出力>
CSVにて
イメージ説明

該当のソースコード

# パスワードに使用する文字 words = 'abcdefghijklmnopqrstuvwxyz0123456789' # パスワード生成 # int(b)でパスワード作成数の数字を取得しています for i in range(int(b)): password=''.join(random.sample(words,12)) print(password) # パスワードをファイルに保存する with open('パスワード生成.csv', 'w') as f: print(password, file=f)

試したこと

『パスワードをファイルに保存する』部分の"w"を"a"にしたり、"newline='\n'"を追加してみたりしましたが、結果は上記【実際の画面】と同じでした。

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

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

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

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

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

guest

回答3

0

ベストアンサー

問題の原因: for 文の中でのファイルの open() と、オープンする時のモードの挙動

open() の 書き込みモードが "w" では、ファイルの内容を上書きすることになります。
繰り返しの中で "w" でオープンすると、繰り返しの度に毎回上書きされることになり、
最後の繰り返しで書き込みされた内容みが残ります。

組み込み関数 open

mode説明
'w'書き込み用に開き、まずファイルを切り詰め*
'a'書き込み用に開き、ファイルが存在する場合は末尾に追記する

md

1# NG: 毎回ファイルの内容を上書している 2 3パスワード1生成 ファイルを開く・書込 4パスワード2生成 ファイルを開く・書込 5パスワード3生成 ファイルを開く・書込

結果は、ファイルを開くときのモードにより異なりますが、
毎回ファイルを開くのも冗長なので、事前に一度のみとした方が良いです。

"a" ならば追加書き込みなので、期待通りに書き込みされるはずですが、
その時のコードはどうなってたのでしょう?


解決策: ファイルの open を for 文の外側にする。
プログラムを以下のような構造にすればうまくいくはずです。

python

1with open('パスワード生成.csv', 'w') as f: 2 for i in range(int(b)): 3 パスワード生成 4 ファイルに書込

md

1# ファイルのopenは一度のみ 2 3ファイルを開く 4パスワード1を生成・ファイルに書込 5パスワード2を生成・ファイルに書込 6パスワード3を生成・ファイルに書込

追記: tkinter タグがついてますが、
上記のプログラムは GUI の中で実行するコードなのでしょうか?

もし、GUI のプログラムでファイル等を出力する場合、
データの規模次第では、ウィンドウがフリーズしないような対策が必要になることも有ります。

投稿2021/04/13 08:04

編集2021/04/13 08:11
teamikl

総合スコア8760

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

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

KiX4Q

2021/04/14 00:44

ご回答ありがとうございます。 また、リンクや詳しい説明もありがとうございます。 "a"にした時ですが、『該当のソースコード』の順序で【with open('パスワード生成.csv', 'a') as f:】としただけでした。 解決策の通りに直したところ、無事生成された複数のパスワードをすべて一度にファイルに保存できました。 追記いただいている件ですが、tkinterで作成するパスワードの入力画面を作成したので、tkinterのタグもつけました。 また、自分でファイル保存の仕組みができなかったので、履歴として、ウィンドウに表示させるようにしていました。 データの規模次第では・・・というのは、パスワードを生成する数が多くなると、フリーズするかもしれないということでしょうか?
teamikl

2021/04/15 02:09

> パスワードを生成する数が多くなると、フリーズするかもしれないということでしょうか? 呼び出し方にもよりますが、スレッド等を利用してないのであればその通りです。 該当の処理をボタンを押したとき等に直接呼び出した場合、 パスワードを生成~ファイルへ書き出ししてる間は、 GUIの描画更新や操作は出来ない状態になってます。 規模次第というのは、数秒程度で終わるようなら許容範囲かもしれませんが、 数分以上かかる規模になると、途中でキャンセルしたい場合でも、ウィンドウを閉じることは出来ず 処理が終わるまでGUI 操作は受け付けない状態なので、スレッドを使う等の対策が必要です。 ---- 一般的なGUIプログラミングに於いて、 「時間の掛かる for 文」は GUI の反応を止める事になるので、 イベントハンドラ内(ボタンクリック時等に呼び出される関数)での利用は避けた方が無難です。 具体的には >for i in range(int(b)): で b の値が巨大だった場合。 別アプローチの対策で、大規模なデータ生成が想定外の場合は、 単純に最大値を設ける range(max(20, int(b)) でも、フリーズ対策できます。
KiX4Q

2021/04/15 07:40

分かりやすく、詳しく説明していただき、本当にありがとうございます。 プログラミング初心者で、独学のため、とても勉強になります。 今回は最大値を設けてみようと思います。 今後はプログラムの動作についても考えながら、適切な処理のプログラムを作っていこうと思います。 ありがとうございました。
guest

0

書込みモードでファイルを開けば

python

1 with open('パスワード生成.csv', 'w') as f: 2 print(password, file=f)

をfor文の中で繰り返しても、毎回からの状態から書き込むので最後のものしか残りません。

python

1 with open('パスワード生成.csv', 'a') as f: 2 print(password, file=f)

というように、appendモードでファイルを開けば追加されていくので全て保存されます。

投稿2021/04/13 06:49

ppaul

総合スコア24670

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

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

KiX4Q

2021/04/14 00:29

ご回答ありがとうございます。
guest

0

python

1for i in range(int(b)): 2 password=''.join(random.sample(words,12))

password 変数をどんどん更新しているだけで、最後の1回分しか結果を保存できませんよね。

追記:
インデントを勘違いしていました。上記回答は勘違いです。
ファイルを開く回数を減らしたほうが効率が良いので、以下のように修正するのが良いと思います。

python

1# 保存するファイルを開く 2with open('パスワード生成.csv', 'w') as f: 3 for i in range(int(b)): 4 password=''.join(random.sample(words,12)) 5 print(password) 6 print(password, file=f)

投稿2021/04/13 05:51

編集2021/04/13 06:57
mather

総合スコア6759

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

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

KiX4Q

2021/04/14 00:31

ご回答ありがとうございます。 最初のコメントでも自分で調べて勉強することができました。 新規のコメントの方で修正したところ、無事できました。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問