我正在尝试使用 PySimpleGUI 构建一个 python GUI 数据库比较器 我在这里遗漏了什么?

I am trying to build a python GUI Database Comparator using PySimpleGUI i missing something here?

我正在尝试构建一个分为两个布局的 GUI 数据库比较器 window。

  1. 从用户那里获取数据库详细信息并测试连接
  2. 获取一个 Excel 文件,其中包含将在 DB 上执行的 SQL 语句,并使用 Datacompy 比较将显示给用户。

我现在面临的问题是

  1. 数据库详细信息应在顶部,输出框应在其下方,反之亦然
  2. 在输入(数据库详细信息)后,当我单击 DB Test1 按钮时,应用程序自行关闭,但未显示出了什么问题(无代码错误,刚刚关闭)

我是 PySimpleGUI 的新手,可能犯了一些愚蠢的错误,请指导我解决我需要重新输入的错误和语句。

这是第一个布局的代码 window :

 import PySimpleGUI as sg
 import re
 import datacompy
 import cx_Oracle
 import pandas as pd


 def read_query(connection, query):
     cursor = connection.cursor()
        try:
           cursor.execute( query )
           header = [ x[0] for x in cursor.description]
           rows = cursor.fetchall()
           return header, rows
       finally:
           if cursor is not None:
           cursor.close()

  def createCon(uname,passw,hname,portnum,sname):

    dsn_str = cx_Oracle.makedsn(host=hname,
                            port=portnum,
                            service_name = sname)
    con = cx_Oracle.connect(user = uname,
                        password = passw,
                        dsn = dsn_str)
    if con == True:
        return con
    else:
        return 0
      


  DB_creds_one = [
     [
        sg.Text("UserName"),
        sg.In(size=(30, 2), enable_events=True, key="-uname_db1-")
     ],
     [
        sg.Text("Password"),
        sg.In(size=(30, 1), enable_events=True, key="-pword_db1-")
     ],
     [
        sg.Text("Hostname"),
        sg.In(size=(30, 1), enable_events=True, key="-hname_db1-")
     ],
     [
        sg.Text("Service Name"),
        sg.In(size=(30, 1), enable_events=True, key="-sname_db1-")
     ],
     [
        sg.Text("Port"),
        sg.In(size=(30, 1), enable_events=True, key="-port_db1-")
     ],
     [   
        sg.Button('Test Con1', key='B1')
     ],

   ]

  DB_creds_two = [
    [
        sg.Text("UserName"),
        sg.In(size=(25, 1), enable_events=True, key="-uname_db2-")
    ],
    [
        sg.Text("Password"),
        sg.In(size=(25, 1), enable_events=True, key="-pword_db2-")
    ],
    [
        sg.Text("Hostname"),
        sg.In(size=(25, 1), enable_events=True, key="-hname_db2-")
    ],
    [
        sg.Text("Service Name"),
        sg.In(size=(25, 1), enable_events=True, key="-sname_db2-")
    ],
    [
        sg.Text("Port"),
        sg.In(size=(25, 1), enable_events=True, key="-port_db2-")
    ],
    [   
        sg.Button('Test Con2',key='B2')
    ],

  ]


layoutprefile = [
    [
        sg.Column(DB_creds_one),
        sg.VSeperator(),
        sg.Column(DB_creds_two),
       [sg.Output(size=(61, 5), key='-output-')],
       [sg.Submit('Proceed'), sg.Cancel('Exit')]
    
    ]
]
 

 window = sg.Window("DB Comparator", layoutprefile)

 while True:    # The Event Loop
    event, values = window.read()
    # print(event, values)  # debug
    if event in (None, 'Exit', 'Cancel'):
         secondwindow = 0
         break
    elif event == 'B1':
         # Test DB Connection 1  return Test_DB1
         uname_d1 = window.FindElement('-uname_db1-')
         pword_d1 = window.FindElement('-pword_db1-')
         hname_d1 = window.FindElement('-hname_db1-')
         sname_d1 = window.FindElement('-sname_db1-')
         port_d1 = window.FindElement('-port_db1-')
         
         if uname_d1 and pword_d1 and hname_d1 and sname_d1 and port_d1 == "":
               print("ENter values")
         else:
               Test_DB1 = createCon(uname_d1,pword_d1,hname_d1,sname_d1,port_d1)
     elif event == 'B2':
        # Test DB Connection 2 return Test_DB2
        uname_d2 = window.FindElement('-uname_db2-')
        pword_d2 = window.FindElement('-pword_db2-')
        hname_d2 = window.FindElement('-hname_db2-')
        sname_d2 = window.FindElement('-sname_db2-')
        port_d2 = window.FindElement('-port_db2-')
        if uname_d2 and pword_d2 and hname_d2 and sname_d2 and port_d2 == "":
             print("ENter values")
        else:
             Test_DB2 = createCon(uname_d2,pword_d2,hname_d2,sname_d2,port_d2)

    if event == 'Proceed':
        if (Test_DB1 and Test_DB2 != 'True'):
            secondwindow = 0
            sg.Popup("Incorrect Database Details Please Verify the Connection Again")
        else:
            window.close()
            secondwindow = 1
            break

if secondwindow != 1:
   exit() 

我不知道这段代码是如何工作的。它给我的消息是布局有误 [] - 可能因为这个我在 window 中没有 sg.Output。但它仍在使用,所有错误消息都发送到 sg.Output,您看不到错误。

正确的布局

layoutprefile = [
    [ 
        sg.Column(DB_creds_one),
        sg.VSeperator(),
        sg.Column(DB_creds_two),
    ],

    [sg.Output(size=(61, 5), key='-output-')],
    [sg.Submit('Proceed'), sg.Cancel('Exit')]
]

现在它在 window 的底部显示我 sg.Output。所有 print() 和错误消息都会发送到此小部件。但最好删除 Output 一段时间以在正常控制台中查看所有错误。


您还有其他问题

它应该与 or== "" 一起用于所有变量 - 检查是否至少有一个元素为空

if uname_d1 == '' or pword_d1 == '' or hname_d1 == '' or sname_d1 == '' or port_d1 == '':

或者您可以将其检查为

if '' in (uname_d1, pword_d1, hname_d1, sname_d1, port_d1):

最终你可以使用空字符串被视为 False

的事实
if not all([uname_d2, pword_d2, hname_d2, sname_d2, port_d2]):

但是还有其他问题。使用 window.FindElement('-uname_db1-') 获取小部件,并从需要 .get() 的小部件中获取文本,或者您应该使用 values[..]

uname_d1 = window.FindElement('-uname_db1-').get()

uname_d1 = values['-uname_db1-']

然后你可以使用.strip()因为有人可能会放空格

uname_d1 = window.FindElement('-uname_db1-').get().strip()

uname_d1 = values['-uname_db1-'].strip()

你检查Test_DB1Test_DB2的方式也有误。需要

(Test_DB1 != True) and (Test_DB2 != True)

或更好

if (Test_DB1 is not True) and (Test_DB2 is not True):

if (Test_DB1 is False) and (Test_DB2 is False):

if (not Test_DB1) and (not Test_DB2):

您可以在第二个 window 中使用 True/False 而不是 1/0

并且在while循环之前设置默认值会更好

secondwindow = True
Test_DB1 = False
Test_DB2 = False

如果你不指定然后直接点击 Process然后你会得到错误 name 'Test_DB1' is not defined 因为它还没有 运行 Test_DB1 = createCon(...)


import PySimpleGUI as sg
import re
import datacompy
import cx_Oracle
import pandas as pd


def read_query(connection, query):
    cursor = connection.cursor()
    try:
       cursor.execute( query )
       header = [x[0] for x in cursor.description]
       rows = cursor.fetchall()
       return header, rows
    finally:
       if cursor is not None:
           cursor.close()

def create_con(user_name, password, host_name, port_number, service_name):

    dsn_str = cx_Oracle.makedsn(host=host_name,
                                port=port_number,
                                service_name=service_name)
    con = cx_Oracle.connect(user=user_name, password=password, dsn=dsn_str)
    
    return con
      
# --- main ---

DB_creds_one = [
     [
        sg.Text("UserName"),
        sg.In(size=(30, 2), enable_events=True, key="-uname_db1-")
     ],
     [
        sg.Text("Password"),
        sg.In(size=(30, 1), enable_events=True, key="-pword_db1-")
     ],
     [
        sg.Text("Hostname"),
        sg.In(size=(30, 1), enable_events=True, key="-hname_db1-")
     ],
     [
        sg.Text("Service Name"),
        sg.In(size=(30, 1), enable_events=True, key="-sname_db1-")
     ],
     [
        sg.Text("Port"),
        sg.In(size=(30, 1), enable_events=True, key="-port_db1-")
     ],
     [   
        sg.Button('Test Con1', key='B1')
     ],
]

DB_creds_two = [
    [
        sg.Text("UserName"),
        sg.In(size=(25, 1), enable_events=True, key="-uname_db2-")
    ],
    [
        sg.Text("Password"),
        sg.In(size=(25, 1), enable_events=True, key="-pword_db2-")
    ],
    [
        sg.Text("Hostname"),
        sg.In(size=(25, 1), enable_events=True, key="-hname_db2-")
    ],
    [
        sg.Text("Service Name"),
        sg.In(size=(25, 1), enable_events=True, key="-sname_db2-")
    ],
    [
        sg.Text("Port"),
        sg.In(size=(25, 1), enable_events=True, key="-port_db2-")
    ],
    [   
        sg.Button('Test Con2',key='B2')
    ],

]


layoutprefile = [
    [ 
        sg.Column(DB_creds_one),
        sg.VSeperator(),
        sg.Column(DB_creds_two),
    ],
    [sg.Output(size=(61, 5), key='-output-')],
    [sg.Submit('Proceed'), sg.Cancel('Exit')]
]
 
window = sg.Window("DB Comparator", layoutprefile)

# default values at start
secondwindow = True
Test_DB1 = False
Test_DB2 = False

while True:    # The Event Loop
    event, values = window.read()
    # print(event, values)  # debug
    if event in (None, 'Exit', 'Cancel'):
        secondwindow = False
        break
    elif event == 'B1':
        # Test DB Connection 1  return Test_DB1
        uname_d1 = values['-uname_db1-'].strip()
        pword_d1 = values['-pword_db1-'].strip()
        hname_d1 = values['-hname_db1-'].strip()
        sname_d1 = values['-sname_db1-'].strip()
        port_d1  = values['-port_db1-'].strip()

        print()
        
        #if uname_d1 == '' or pword_d1 == '' or hname_d1 == '' or sname_d1 == '' and port_d1 == '':
        #if not all([uname_d1, pword_d1, hname_d1, sname_d1, port_d1]):
        if '' in (uname_d1, pword_d1, hname_d1, sname_d1, port_d1):
            print("Enter values")
        else:
            Test_DB1 = create_con(uname_d1, pword_d1, hname_d1, sname_d1, port_d1)
            
    elif event == 'B2':
        # Test DB Connection 2 return Test_DB2
        uname_d2 = values['-uname_db2-'].strip()
        pword_d2 = values['-pword_db2-'].strip()
        hname_d2 = values['-hname_db2-'].strip()
        sname_d2 = values['-sname_db2-'].strip()
        port_d2  = values['-port_db2-'].strip()
        
        #if uname_d2 == '' or pword_d2 == '' or hname_d2 == '' or sname_d2 == '' and port_d1 == '':
        #if not all([uname_d2, pword_d2, hname_d2, sname_d2, port_d2]):
        if '' in (uname_d2, pword_d2, hname_d2, sname_d2, port_d2):
            print("Enter values")
        else:
            Test_DB2 = create_con(uname_d2, pword_d2, hname_d2, sname_d2, port_d2)

    if event == 'Proceed':
        if not Test_DB1 and not Test_DB2:
            sg.Popup("Incorrect Database Details Please Verify the Connection Again")
        else:
            window.close()
            break

#    if not secondwindow:
exit() 

您的代码看起来格式不正确。

这里列出了一些问题,

  1. 布局错误
layoutprefile = [
    [
        sg.Column(DB_creds_one),
        sg.VSeperator(),
        sg.Column(DB_creds_two),
       [sg.Output(size=(61, 5), key='-output-')],
       [sg.Submit('Proceed'), sg.Cancel('Exit')]
    
    ]
]

如果需要水平布局

layout = [
    [sg.Button("Hello1"), sg.VerticalSeparator(), sg.Button("Hello2")],
]

或垂直布局

layout = [
    [sg.Button("Hello1")],
    [sg.HorizontalSeparator()],
    [sg.Button("Hello2")],
]
  1. 获取 sg.Input
  2. 值的方法错误
uname_d1 = window.FindElement('-uname_db1-')    # It can be window['-uname_db1-']

它只是获取元素sg.input的元素。获取 sg.Input

的值
uname_d1 = values['-uname_db1-']
  1. 如果Test_DB1Test_DB2的两个值在下面的逻辑语句中都会得到错误的结果
if (Test_DB1 and Test_DB2 != 'True'):

也许应该

if not (Test_DB1 and Test_DB2):
  1. 函数 create_con 调用时的参数顺序错误。
#      def createCon(uname,   passw,   hname,   portnum, sname):
Test_DB1 = createCon(uname_d1,pword_d1,hname_d1,sname_d1,port_d1)
  1. portnum 可能会在传递给函数 createCon
  2. 之前转换为整数