PySide2を使ったPyshonのツール作成

Pythonの初学者ですが、初めてツールを作成しました。
PySide2でcsvファイルを読み込んで、JSON,YAMLファイルに変換するだけのツールです。

![Json_yanlfikemaker.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/928107/60860664-af2e-1cf3-7d76-3c3cb05115c9.jpeg)

これを使った目的は学習でDockerCompose.Ymlファイルを作成するが、慣れていないので見えないバグにいつも悩まされる。
一括で変換してなるべく入力ミスをなくしたい。

PySide2を勉強していたので、その復習も兼ねて作りました。

・QfileDialogでcsvファイルを選択して、ListWidgetに内容を表示させる。
・ListWidgetの情報をJSONボタンをクリックした時に情報を取得してJSONファイルに変換して、ファイルを書き込む。
・ListWidgetの情報をYAMLボタンをクリックした時に情報を取得してYAMLファイルに変換して、ファイルを書き込む。

`````
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import csv
import json
import yaml
import codecs
import sys

from  PySide2 import QtWidgets, QtCore

#init関数を定義
class Jymaker(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("Json Yaml fileMaker")

        self.build_ui()
        #SignalとSlotを設定
        self.connect_signal_slot()

    def callback_line_edit_editingFinished(self):
        file = self.line_edit.text()

        if not file.endswith(".csv"):
            return

        url = QtCore.QUrl(file)
        if url.isLocalFile():
            file = url.toLocalFile()
        
        if os.path.exists(file):
            self.line_edit.setText(file)

            json_list = self.load_csv(file)
            self.listwgt.clear()
            self.listwgt.addItems(json_list)

#Openボタンを押したときの挙動を設定
    def callback_file_dialog_button_clicked(self):
        file, filter_ = QtWidgets.QFileDialog.getOpenFileName(
            self, "Open CSV", "C:/Users/User/Documents/Jymaker/csv", "CSV (*.csv)"
        )

#csvファイルの中の情報を取り出す
#listWedgetに情報を入れていく
        if file:
            self.line_edit.setText(file)
            json_list = self.load_csv(file)
            self.listwgt.clear()
            self.listwgt.addItems(json_list)
#returnで返された、変数を受け取り表示させる。
           

#JSONボタンを押したときにの処理
    def callback_create_file_button_clicked(self):
        jsdata = []
        for row in range(self.listwgt.count()):
            item = self.listwgt.item(row)
            jsdata.append(item.text())

        filename = "C:/Users/User/Documents/Jymaker/json/sample.json"
        with open(filename, "w", encoding="utf_8") as f:
            json.dump(jsdata, f ,indent=4)

#メッセージボックス
        QtWidgets.QMessageBox.about(
            self,
            "json file was created.",
            "json file was created."
        )
       
#YAMLボタンを押したときにの処理
    def callback_create_yaml_button_clicked(self):
        yamldata = []
        for row in range(self.listwgt.count()):
            item = self.listwgt.item(row)
            yamldata.append(item.text())

        filename = "C:/Users/User/Documents/Jymaker/yml/sample.yml"
        with codecs.open(filename, 'w', 'utf-8') as f:
            yaml.dump(yamldata, f, encoding='utf-8', allow_unicode=True)

#メッセージボックス
        QtWidgets.QMessageBox.about(
            self,
            "Yaml file was created.",
            "Yaml file was created."
        )

    #パーツを作る関数の定義
    def build_ui(self):
        self.line_edit = QtWidgets.QLineEdit()
        self.file_dialog_button = QtWidgets.QPushButton("Open")
        self.line = QtWidgets.QFrame()
        self.line.setFrameStyle(QtWidgets.QFrame.HLine | QtWidgets.QFrame.Sunken)
        self.listwgt = QtWidgets.QListWidget()
        self.create_file_button = QtWidgets.QPushButton("JSON")
        self.create_yaml_button = QtWidgets.QPushButton("YAML")

     #GUIを表示させるためのレイアウト設置
        form_layout = QtWidgets.QFormLayout()
        form_layout.addRow("CSV File", self.line_edit)
        form_layout.addRow("", self.file_dialog_button )
        form_layout.addRow(self.line)
        form_layout.addRow("File", self.listwgt)
        form_layout.addRow(self.create_file_button)
        form_layout.addRow(self.create_yaml_button)
        self.setLayout(form_layout)

    #SignalとSlotを繋げる処理を行う関数
    def connect_signal_slot(self):
        self.line_edit.editingFinished.connect(self.callback_line_edit_editingFinished)
        self.file_dialog_button.clicked.connect(self.callback_file_dialog_button_clicked)
        self.create_file_button.clicked.connect(self.callback_create_file_button_clicked)
        self.create_yaml_button.clicked.connect(self.callback_create_yaml_button_clicked)

#csvファイルの内容をを読み込む。
# 読み込んだ内容をQListWidgetItemに返して表示させる。
    def load_csv(self, file):
        json_list =[]
        with open(file, "r", encoding="utf_8") as f:
            reader = csv.reader(f)
            for row in reader:
                json_list.append(",".join(row))

        return(json_list)

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    win = Jymaker()
    win.show()
    sys.exit(app.exec_())

````
苦労したこと
１．listWedgetに情報を表示せせるのに苦労しました。
思うように情報が表示できない。
エラーが発生しないから、どこが間違っているのか分からない。
listWedgetが間違っているとの指摘もあり、 QTableWidget や QTableView への表示が適切との御意見を頂きましたが、

teratail.comに質問を投稿して、
引数に,を入れることを教えて頂き、無事、情報を表示せることができました。

````
json_list.append(",".join(row))
```

２．listWedgetからの情報を取得してJsonファイルに変換できない。
csvファイルから単にJsonファイルに変換するのなら、Qiitaに情報があります。
listWedgetの情報を取得してＪＳＯＮファイルに変換できない。
ファイルが出力されない。
ググっても分からなくて心が折れそうになりました。
QListWidgetのitermを取り出して、文字情報を取り出すには、text()メソッドを使いました。
そこからJSONファイルを作成するコードを書いたのですが、上書きされてしまい最後の行しか内容がない。
これが問題の行


````
    def callback_create_file_button_clicked(self):
            for row in range(self.listwgt.count()):
                item = self.listwgt.item(row)
                jsonlist = item.text()
            filename = "C:/Users/User/Documents/Jymaker/json/sample.json"
            with open(filename, "w", encoding="utf_8") as f:
                json.dump(jsonlist, f)
           

````
上のコードは、jsonlistという変数にitem.text()の内容が上書きされて保持される。

Udemyの先生に教えて頂き、これを以下のように修正

````
def callback_create_file_button_clicked(self):
        jsdata = []
        for row in range(self.listwgt.count()):
            item = self.listwgt.item(row)
            jsdata.append(item.text())

        filename = "C:/Users/User/Documents/Jymaker/json/sample.json"
        with open(filename, "w", encoding="utf_8") as f:
            json.dump(jsdata, f ,indent=4)

````
変数を変更しましたが、jsdata変数を初期化して、list.appendで、リストに要素を追加するようにしました。

これによりcsvフィルの内容が全部、JSONファイルに変換され保存できました。
YAMLファイルも同様ですが、PyYAML というパッケージをインストールする必要があります。
書き込むとき(日本語が入っているとき)は.codecsをインポートする必要があります。

今後について
JSONファイルもYAMLファイルも文法的に問題ないか専用のチェッカーＷebサービスで確認したら問題はありませんでした。
DockerCompose.ymlを生成し問題なく出力されたのですが、csvファイルのフォーマットに注意が必要。
これが正常に使えるか検証。

今度はJSONファイルやYAMLファイルをcsvファイルに変換する機能を実装したい。
コード上でファイル名を指定しているので、ＧＵＩでファイル名を指定できるようにしたい。
PyInstallerを使いexeファイルに変換する。
listWedgetからQTableWidgetに変更。


もう少し、分かりやすくしたいので修正予定。