【问题标题】:How can I execute a python script dependent on extracting file name in another python gui script?如何执行依赖于在另一个 python gui 脚本中提取文件名的 python 脚本?
【发布时间】:2021-07-21 04:33:05
【问题描述】:

我创建了一个 python 脚本 (NoShowCalc.py),它使用 3 个选定的 excel 文件(booked_file_patharrived_file_pathvlookup_file_path)自动进行数据清理和分析。但是,我希望这一切都通过 GUI 执行,所以我启动了一个单独的 (GUI.py) 脚本来创建一个带有浏览按钮的界面,该按钮将获取这些文件路径名,然后这将为我提供执行所需的NoShowCalc.py 脚本。一旦选择了这些 excel 文件,就会出现另一个按钮来执行 NoShowCalc.py 脚​​本。然而,我做到了,它奏效了!但我不知道我改变了什么,现在两个不同的 py 文件没有连接。

这是NoShowGUI.py 脚本中的脚本:

def open_file():
browse_text.set('Loading...')
booked_file_path = askopenfile(parent=root, mode='rb', title='Choose a file', filetype=[('CSV file', '*.csv')])
if booked_file_path:
    read_csv = (booked_file_path)
    browse_text.set('Loaded')
def run():
    os.system('NoShow_Calc.py')
    calculate_text.set("Calculating...")
#Calculate button
calculate_text = tk.StringVar()
calculate_btn = tk.Button(root, textvariable=calculate_text, command=lambda:run(), font='Calibri', fg='black', height=1, width=15)
calculate_text.set("Calculate No Show")
calculate_btn.grid(column=2, row=9)

这些是NoShowCalc.py 脚本中的第一行:

import pandas as pd 

booked = pd.read_csv(booked_file_path, parse_dates=['Appointment Date'])
arrived = pd.read_csv(arrived_file_path, parse_dates=['Appointment Date'])
vlookup = pd.read_excel(vlookup_file_path)

不断弹出的错误是NameError: name 'booked_file_path' is not defined。我不知道它以前是如何运行的,现在这个错误正在弹出,因为它不能再与其他 py 文件对话了。我做错了什么?

【问题讨论】:

  • 总是将完整的错误消息(从单词“Traceback”开始)作为文本(不是截图,不是链接到外部门户)有问题(不是评论)。还有其他有用的信息。
  • 如果您使用os.system() 运行代码,那么您不能使用其他脚本中的变量。仅当使用 import 将一个脚本加载到另一个脚本时才能执行此操作 - 就像使用模块 pandas
  • 使用os.system()你只能发送值作为参数os.system('NoShow_Calc.py selecte_filename')并使用sys.argvbooked_file_path = sys.argv[1]NoShow_Calc.py中获取这个值。
  • 对不起,我不知道我是否听懂了你的意思。
  • 我说如果你以os.system() 运行它,那么在NoShowCalc.py 内你不能使用来自文件NoShowGUI.py 的变量booked_file_path,因为它在系统和分离进程中作为分离进程运行脚本不共享变量。

标签: python tkinter operating-system


【解决方案1】:

如果您使用os.system() 或使用模块subprocess 运行脚本,则不能使用其他脚本中的变量。它们作为独立的进程运行,不能共享变量(或内存中的数据)

您只能发送一些文本值作为参数

 os.system('NoShow_Calc.py ' + booked_file_path)

然后您可以使用sys.argv 将其放入NoShow_Calc

import pandas as pd 
import sys

booked_file_path  = sys.argv[1]

booked = pd.read_csv(booked_file_path, parse_dates=['Appointment Date'])
arrived = pd.read_csv(arrived_file_path, parse_dates=['Appointment Date'])
vlookup = pd.read_excel(vlookup_file_path)

如果您需要其他变量,那么您必须以相同的方式发送其他值

 os.system('NoShow_Calc.py ' + booked_file_path + ' ' + other_filename)

booked_file_path = sys.argv[1]
other_filename = sys.argv[2] 
# etc.

但是使用os.system() 你不能将结果booked, arrived, vlookupNoShow_Calc 发送到NoShowGUI

您可以使用subprocess 来执行此操作,但它只能作为文本发送 - 所以NoShow_Calc 必须使用print() 来显示所有结果,NoShowGUI 必须将此文本解析为预期的结构 - 即.列表、字典、DataFrame


您最好使用importNoShow_Calc.py 加载代码,然后所有代码在同一个进程中运行,因此所有代码都可以访问相同的变量 - 它不需要转换为文本并从文本返回.

为了让它更好,我把代码放在函数中

import pandas as pd 

def my_function(booked_file_path, arrived_file_path, vlookup_file_path):
    booked = pd.read_csv(booked_file_path, parse_dates=['Appointment Date'])
    arrived = pd.read_csv(arrived_file_path, parse_dates=['Appointment Date'])
    vlookup = pd.read_excel(vlookup_file_path)

    return booked, arrived, vlookup

然后在NoShowGUI 中你可以导入它并像任何其他函数一样使用

from NoShow_Calc import my_function

booked, arrived, vlookup = my_function(booked_file_path, arrived_file_path, vlookup_file_path)

编辑:

我编写了最少的工作代码。我把它减少到只有一个文件名。

NoShow_Calc.py

import pandas as pd 

def calc(booked_file_path): #, arrived_file_path, vlookup_file_path):
    booked = pd.read_csv(booked_file_path, parse_dates=['Appointment Date'])
    #arrived = pd.read_csv(arrived_file_path, parse_dates=['Appointment Date'])
    #vlookup = pd.read_excel(vlookup_file_path)
    
    return booked #, arrived, vlookup

NoShowGUI.py

import tkinter as tk
from tkinter.filedialog import askopenfilename   # instead of `askopenfile`

# adding directory with this script to `sys.path` before `import NoShow_Calc`
# to make sure that `import` will search `NoShow_Calc.py` in correct folder even when GUI will be run from different folder

import os
import sys

HOME_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(HOME_DIR)

import NoShow_Calc

print('HOME_DIR:', HOME_DIR)

def select_filename():
    global booked_file_path  # inform function that it has to assign value to external/global variable 

    text_log.insert('end', 'Selecting ...\n')
    
    # use `askopenfilename` instead of `askopenfile` 
    # because I need only filename, not opened file (pandas will open it on its own)
    
    booked_file_path = askopenfilename(parent=root,                                        
                                       title='Choose a file', 
                                       #initialdir='/home/furas',
                                       filetypes=[('CSV file', '*.csv')])
    
    if booked_file_path:
        text_log.insert('end', f'Selected: {booked_file_path}\n')
    else:
        text_log.insert('end', f'Not selected\n')

def run():
    text_log.insert('end', "Calculating...\n")

    if booked_file_path is None:
        text_log.insert('end', "File booked_file_path not selected !!!")
        return
    #elif arrived_file_path is None:
    #    text_log.insert('end', "File arrived_file_path not selected !!!")
    #    return
    #elif vlookup_file_path is None:
    #    text_log.insert('end', "File vlookup_file_path not selected !!!")
    #    return
    else:        
        root.update()  # force tkinter to update text in text_log at once (not when it exits function `run`)
        result = NoShow_Calc.calc(booked_file_path)# , arrived_file_path, vlookup_file_path)

    text_log.insert('end', "Result:\n")
    text_log.insert('end', str(result.head()) + "\n")
    
# --- main ---    

booked_file_path = None  # default value at start (so in `run` I can check `None` to see if I selecte filename)
#arrived_file_path = None
#vlookup_file_path = None

root = tk.Tk()

text_log = tk.Text(root)
text_log.grid(column=0, row=0)

select_btn = tk.Button(root, text="Select File Name", command=select_filename)
select_btn.grid(column=0, row=1)

calculate_btn = tk.Button(root, text="Calculate", command=run)
calculate_btn.grid(column=0, row=2)

root.mainloop()

【讨论】:

  • 抱歉,这不起作用。我必须先检索文件位置,然后进行计算。我仍然得到相同的 NameError 'booked_file_path' is not defined 但这次它在我的 NoShowGUI.py 文件中说它
  • 好吧,这可能是其他问题 - 您在函数 open_file 中创建 local 变量 booked_file_path 并且它在其他函数中不存在(例如 run 。您应该添加行 @987654352 @ inside open_file 通知此函数您要为外部/全局变量booked_file_path 赋值 - 然后run 应该可以访问全局booked_file_path
  • 我添加了最小的工作代码,它使用import 从其他文件运行代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多