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

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

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

自身のプラットフォーム・プログラム・データセットに対して、外部ソースを取り込むプロセスをimportと呼びます。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Tkinter

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

Python

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

Q&A

解決済

1回答

1544閲覧

PYTHONのファイル分割時エラー

akiteru

総合スコア21

import

自身のプラットフォーム・プログラム・データセットに対して、外部ソースを取り込むプロセスをimportと呼びます。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Tkinter

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

Python

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

1グッド

1クリップ

投稿2020/03/14 08:30

編集2020/03/16 07:57

既に同じ質問を3回目となる投稿です、投稿ルール、「編集」、「削除」等の処理方法が今一つ理解不足でご迷惑をかけています。(これからは言い訳です)投稿のコード部分のインデントが質問入力画面では有るにもかかわらず新着の質問で表示させると全て削除され左側揃えとなっています。2回目投稿ではご指摘で<code>で挿入したのですが頭尾にある「'''」を文面作成フォームで削除しました(入力画面ではインデント有)。この為と思われますが投稿の様にすべて左揃えになっていました。
下記文面はコード部分が入力フォームとプレビュー画面ともにインデント有で表示されています。
正常に表示されるようでしたら、よろしくお願いします。
【追記】ご指摘によりPyPostTblの定義を追加してあります

(1) //////// 初心者です。PYTHONでファイルを分割(親子関係で)したいのですがエラーが発生。対策を教えて下さい。
又、修正した方が良い部分があればご指摘ください。

(2) /////// 下記ソースコードは正常に動作します。これをメインプログラム(parent.py)と画面作成部分(child1.py)とボタンクリック動作部分(child2.py)にファイルに分割したい。

(3) 正常に動作する元コード及びエラーが出る三分割後コードは下記の通りです

////////////元コード(original.py):正常に動作する

#*** original.py import tkinter as tk import tkinter.ttk as ttk import sqlite3 class MainWindow(ttk.Frame): def __init__(self, parent): super(MainWindow, self).__init__(parent) self.parent = parent #********画面作成 self.create_notebook() self.pack() def create_notebook(self): # ノートブック self.nb = ttk.Notebook(self) # タブの作成 self.tab1 = tk.Frame(self.nb) self.nb.add(self.tab1, text='入力', padding=3) self.nb.pack(expand=1, fill='both') #*******検索条件ページ画面(タブ1) # ページ表題ラベルの設定 self.label1_1 = tk.Label(self.tab1,text="【検索条件】",font=("",16),height=2) self.label1_1.pack(fill="x") # ふりがなのラベルとエントリーの設定 self.frame1_1 = tk.Frame(self.tab1,pady=10) self.frame1_1.pack() self.label1_1 = tk.Label(self.frame1_1,font=("",14),text="フリガナ") self.label1_1.pack(side="left") self.entry1_1 = tk.Entry(self.frame1_1,font=("",14),justify="center",width=15) self.entry1_1.pack(side="left") # 検索ボタンの設定 self.button1_4 = tk.Button(self.tab1,text="検 索",font("",14),width=5,bg="gray",command=self.show_datalist) self.button1_4.pack() #**********データベース接続 self.conn = sqlite3.connect("PyPostDb.db") self.cur = self.conn.cursor() # ****検索実行ボタンが押された処理 def show_datalist(self): huri = str.strip(self.entry1_1.get()) #*********検索条件文の作成 sql = "SELECT * FROM PyPostTbl WHERE PyPostTbl.Huri LIKE '%" + huri + "%'" # SELECT文で取得した各レコードを繰り返し取得 self.cur.execute(sql) r = self.cur.fetchall() if r==None: self.lblStatus.configure(text="登録データはありません。") else: for row in r: print(row[2],row[4]) def quit(self, event=None): # 終了時の処理 #self.conn.close() self.master.destroy() application = tk.Tk() application.geometry("1000x600") application.title('PyPost') window = MainWindow(application) application.protocol('WM_DELETE_WINDOW', window.quit) application.mainloop()

///////////  エラーとなる三分割後コード(parent.py child1.py child2.py)
///親コード(parent.py)

# ******* parent.py import tkinter as tk import tkinter.ttk as ttk import sqlite3 import child1 as ch1 import child2 as ch2 class MainWindow(ttk.Frame): def __init__(self, parent): super(MainWindow, self).__init__(parent) self.parent = parent #**********データベース接続 self.conn = sqlite3.connect("PyPostDb.db") self.cur = self.conn.cursor() # *********** ここにインポートしたモジュールを置きました ******************* #********画面作成 ch1.create_notebook(self) self.pack() # ****検索実行ボタンが押された処理 ch2.show_datalist(self) def quit(self, event=None): # 終了時の処理 self.conn.close() self.master.destroy() application = tk.Tk() application.geometry("1000x600") application.title('PyPost') window = MainWindow(application) application.protocol('WM_DELETE_WINDOW', window.quit) application.mainloop()

//////子コード1(child1.py)

#**** child1.py import tkinter as tk import tkinter.ttk as ttk import sqlite3 import child2 as ch2 # **********画面作成 def create_notebook(self): # ノートブック self.nb = ttk.Notebook(self) # タブの作成 self.tab1 = tk.Frame(self.nb) self.nb.add(self.tab1, text='入力', padding=3) self.nb.pack(expand=1, fill='both') #*******検索条件ページ画面(タブ1) # ページ表題ラベルの設定 self.label1_1 = tk.Label(self.tab1,text="【検索条件】",font=("",16),height=2) self.label1_1.pack(fill="x") # ふりがなのラベルとエントリーの設定 self.frame1_1 = tk.Frame(self.tab1,pady=10) self.frame1_1.pack() self.label1_1 = tk.Label(self.frame1_1,font=("",14),text="フリガナ") self.label1_1.pack(side="left") self.entry1_1 = tk.Entry(self.frame1_1,font=("",14),justify="center",width=15) self.entry1_1.pack(side="left") # 検索ボタンの設定 self.button1_4 = tk.Button(self.tab1,text="検索",font=("",14),width=5,bg="gray",command=ch2.show_datalist) self.button1_4.pack()

//// 子コード2(child2.py)

# **** child2.py import tkinter as tk import tkinter.ttk as ttk import sqlite3 import child1 as ch1 # ******各種アクション集 def show_datalist(self): huri = str.strip(self.entry1_1.get()) #*********検索条件文の作成 sql = "SELECT * FROM PyPostTbl WHERE PyPostTbl.Huri LIKE '%" + huri + "%'" # SELECT文で取得した各レコードを繰り返し取得 self.cur.execute(sql) r = self.cur.fetchall() if r==None: self.lblStatus.configure(text="登録データはありません。") else: for row in r: print(row[2],row[4])

(4) //////////// 分割前はフォームが表示された後、「フリガナ」を入力し「検索」ボタンをクリックすると結果が表示されます。
これに対し分割後はフォームが表示された後、「フリガナ」を入力する以前に全登録データが表示されます。その後「フリガナ」を入力し「検索」ボタンをクリックすると下記エラーが表示され検索結果は表示されません
raceback (most recent call last):
File "C:\Users\akiteru\AppData\Local\Programs\Python\Python38\lib\tkinter\init.py", line 1883, in call
return self.func(*args)
TypeError: show_datalist() missing 1 required positional argument: 'self'

(5) /////// PyPostTblの定義
DB Browser for SQLiteで表示されるテーブルの定義は下記の通りです。

CREATE TABLE "PyPostTbl" (
"Id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"KuwakeId" INTEGER NOT NULL,
"Name" TEXT NOT NULL,
"Huri" TEXT NOT NULL UNIQUE,
"Add1" TEXT,
"Add2" TEXT,
"Add3" TEXT,
"PostNo" TEXT,
"Tel1" TEXT,
"Tel2" TEXT,
"Email" TEXT,
"Nennga" TEXT,
"Seibo" TEXT,
"Bikou1" TEXT,
"Bikou2" TEXT
);

s.k👍を押しています

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

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

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

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

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

hoshi-takanori

2020/03/14 09:17 編集

質問は編集できますので、ソースコードを code 機能を使ってちゃんと表示されるようにしてください。このままだとどこからどこまでがどのファイルかわからないし、python ではインデントが重要なのですが、インデントも失われているので。やり方は、以下の記事を参考にしてください。 https://apuridasuo.hatenablog.com/entry/2019/10/20/220308
y_waiwai

2020/03/14 09:12

このままではコードが読めないので、質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
akiteru

2020/03/16 01:57

やっと「編集」ボタンを発見し、その後もトラブりましたがほぼ理解いただける状態かな?と思われる投稿になりました
akiteru

2020/03/16 07:59

PyPostTblの定義を追加しました
guest

回答1

0

ベストアンサー

エラーの該当箇所

python

1# child1.py 2# 検索ボタンの設定 ... のボタンが押されたときに実行されるcommand 3command=ch2.show_datalist

原因: "インスタンス・メソッド"と"関数"の違い

ボタンが押されたときに実行されるのは ch2.show_datalist() (関数呼び出し)なので
引数 self がなく呼び出される為に、エラーが出ています。

解決策:
手短な解決策としては、ボタンが押されたときに呼び出されるコードに
引数を渡すようにすることで解消出来ます。

command=lambda:ch2.show_datalist(self)

original.py の元のコード command=self.show_datalist は、インスタンスメソッドの呼び出しで
メソッド呼び出しでは、引数の self は省略可能になる為、引数を渡す必要はありません。


改善案:
メソッドの分割について

別ファイルの関数を呼び出す方法で分割されていましたが、
これをMainWindowクラスのメソッドとして呼び出す方法を紹介します。
(オブジェクト指向の用語について学習されているのを前提として)

※これはおすすめの分割方法という訳ではなく、Pythonのクラスの実装でのみ使えるTipsです。


python

1import child1 as ch1 2import child2 as ch2 3 4class MainWindow(ttk.Frame): 5 6 # 別ファイルで定義した関数を、インスタンスメソッドにする。 7 create_notebook = ch1.create_notebook # ここで from child1 import create_notebook でも良い 8 show_datalist = ch2.show_datalist 9 10 def __init__(self, parent): 11 super(MainWindow, self).__init__(parent) 12 self.parent = parent 13 14 #**********データベース接続 15 self.conn = sqlite3.connect("PyPostDb.db") 16 self.cur = self.conn.cursor() 17 18# *********** ここにインポートしたモジュールを置きました ******************* 19 #********画面作成 20 self.create_notebook() # <-- ch1.create_notebook(self) 21 self.pack() 22 23 # ****検索実行ボタンが押された処理 24 self.show_datalist() # <-- ch2.show_datalist(self) 25 26 def quit(self, event=None): 27 # 終了時の処理 28 self.conn.close() 29 self.master.destroy()

同じクラスのインスタンスメソッドとすることで、
self を通じて別ファイルで定義した関数を、メソッドとして呼び出す事が出来ます。
>メソッド呼び出し→selfを渡す関数呼び出し といった変更作業が不要になります。


補足: 上記の分割方法について注意点
IDEやドキュメント生成ツールではメソッドと認識されない可能性があります。
あまり多用する分割方法ではなく、飽くまで「メソッドを関数にして (インスタンス)self を渡す」の代用です。
オブジェクト指向に於いては、役割毎に別クラスに分割するのが一般的です。

投稿2020/03/16 11:11

編集2020/03/16 11:37
teamikl

総合スコア8760

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

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

akiteru

2020/03/17 08:07

ありがとうございました。「解決策」にて希望の動作しました。「lambda」は知らなかったので、これから勉強します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問