如何在一个 Python 脚本中使用另一个脚本的数值。

huangapple go评论113阅读模式
英文:

How to use value from one python script to another

问题

我有两个Python脚本

Script1.py 包括

``` python
import tkinter as tk

def button_click():
    exec(open("script2.py").read())
    
def main():
    global entry_field
    root = tk.Tk()
    entry_field = tk.Entry(root)
    entry_field.pack()

    button = tk.Button(root, text="Click me!", command=button_click)
    button.pack()  

    root.mainloop()
    
if __name__ == "__main__":
    main()

第二个Python脚本是"Script2",包括:

import tkinter as tk
import script1

root = tk.Tk()

label = tk.Label(root, text=script1.entry_field.get())
label.pack()

root.mainloop()

我的想法是:我想要传递我在script1.py中键入的值,在之后我想要在script2.py中使用这个值并在标签上显示出来。

当我运行这段代码时,我遇到了一个错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "c:\Users\User\Desktop\Skaala\Skaala project\Test folder\script1.py", line 4, in button_click
    exec(open("script2.py").read())
  File "<string>", line 6, in <module>
AttributeError: module 'script1' has no attribute 'entry_field'

我会感激任何帮助。

编辑:

我稍微更改了代码,并移除了 "if name == "main":" 语句,现在它只实现了一半。当我运行 "Script1.py" 时,它会打开两次。这就是为什么我使用了 "if name == "main":",因为 "Script2.py" 从 "Script1.py" 导入数据,然后再次运行整个脚本。


<details>
<summary>英文:</summary>

I have 2 python scripts.

Script1.py includes:

``` python
import tkinter as tk

def button_click():
    exec(open(&quot;script2.py&quot;).read())
    
def main():
    global entry_field
    root = tk.Tk()
    entry_field = tk.Entry(root)
    entry_field.pack()

    button = tk.Button(root, text=&quot;Click me!&quot;, command=button_click)
    button.pack()  

    root.mainloop()
    
if __name__ == &quot;__main__&quot;:
    main()

Second python script is "Script2" and includes:

import tkinter as tk
import script1

root = tk.Tk()

label = tk.Label(root, text=script1.entry_field.get())
label.pack()

root.mainloop()

My idea is: I want to pass value which I typed into entry field in script1.py, after I want to use this value and show it with label on script2.py.

When I run this code I'm getting an error:

Exception in Tkinter callback
Traceback (most recent call last):
  File &quot;C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py&quot;, line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File &quot;c:\Users\User\Desktop\Skaala\Skaala project\Test folder\script1.py&quot;, line 4, in button_click
    exec(open(&quot;script2.py&quot;).read())
  File &quot;&lt;string&gt;&quot;, line 6, in &lt;module&gt;
AttributeError: module &#39;script1&#39; has no attribute &#39;entry_field&#39;

I will appreciate for any help.

EDIT:

I've changed code a little bit, and removed "if name == "main":" statement, and now it works on half way. When I run "Script1.py" it opening twice. Thats why I used "if name == "main":", because "Script2.py" importing data from "Script1.py" and it runs full script again.

如何在一个 Python 脚本中使用另一个脚本的数值。

答案1

得分: 2

entry_fieldbuttonroot只存在于Script1中main函数的作用域内。如果你想在main函数外部访问它们,你需要将它们的声明移到全局作用域之外。

编辑:

在Python中,类和函数定义了_作用域_。作用域确定了标签指代什么值。如果你在函数内部声明了某个东西,那个值只能在该函数的作用域内访问。也就是说,只能在函数体内部访问。在下面的例子中,我们有一个全局声明 g = 1 和一个函数 f1,它赋值 g = 2。请注意,这不是相同的 g。它为一个全新的值创建了一个全新的标签。

g = 1

def f1():
    # 创建一个本地变量 g,它与全局变量 g 不同
    # 并且在函数之外是不可见的。
    # 值为2,但全局的 g 仍然是1。
    g = 2

def f2():
    # 这次,变量 g 被声明为全局的,
    # 因此 f2 内的任何对 g 的引用都将引用全局的 g。
    global g
    g = 2

def f3():
    # 这次的代码将会崩溃,因为我们同时尝试
    # 给本地变量 g 赋值和读取全局变量 g。
    g += 1

f1()
print(g) # 打印 1

f2()
print(g) # 打印 2

f3() # 崩溃

exec 函数接受一个输入字符串并在当前作用域中运行它,因此你在答案中包含的代码实际上等同于这个:

import tkinter as tk

def button_click():
    # 这一行:
    # exec(open("script2.py").read())

    # 等同于将代码粘贴到这里:
    import tkinter as tk
    import script1

    root = tk.Tk()

    label = tk.Label(root, text=script1.entry_field.get())
    label.pack()

    root.mainloop()

    
def main():
    global entry_field
    root = tk.Tk()
    entry_field = tk.Entry(root)
    entry_field.pack()

    button = tk.Button(root, text="Click me!", command=button_click)
    button.pack()  

    root.mainloop()
    
if __name__ == "__main__":
    main()

这会造成问题,因为只有在调用main之后,Script1才会有entry_field属性。

我不太清楚为什么你要将这些代码分成两个不同的文件,并通过在它上面调用 exec 来“导入”Script2。你为什么这样做呢?有更好的将代码拆分成多个文件的方式,比如只需使用 import <filename>。通常应该非常谨慎地使用exec

英文:

entry_field, button and root only exist inside the scope of the function main in Script1. If you want to access them outside the main function, you need to move their declaration outside the function into the global scope.

Edit:

In Python, classes and functions define scope. Scope is what determines what labels refer to what values. If you declare something inside a function, that value will only be accessible inside that function's scope. I.e, anything inside the function body. In the example below, we have a global declaration g = 1 and a function f1 that assigns g = 2. Note that this is NOT THE SAME g. It's creating an entirely new label for an entirely new value.

g = 1

def f1():
    # Creates a local variable g which is
    # different from the global variable g
    # and is not visible outside the function.
    # The value is 2, but the global g is still 1.
    g = 2

def f2():
    # This time, the variable g is declared
    # as global, so any references to g inside
    #&#160;f2 will refer to the global g.
    global g
    g = 2

def f3():
    #&#160;This time the code will actually crash with
    #&#160;an UnboundLocalError, because the we&#39;re trying
    #&#160;to assign the local variable g at the same time
    #&#160;as we&#39;re trying to read the global variable g.
    g += 1

f1()
print(g) #prints 1

f2()
print(g) #prints 2

f3() # crashes

The exec function takes an input string and runs it in the current scope, so the code you included in your answer is actually equivalent to this:

import tkinter as tk

def button_click():
    # This line:
    #&#160;exec(open(&quot;script2.py&quot;).read())

    # Is the same as just pasting the code here:
    import tkinter as tk
    import script1

    root = tk.Tk()

    label = tk.Label(root, text=script1.entry_field.get())
    label.pack()

    root.mainloop()

    
def main():
    global entry_field
    root = tk.Tk()
    entry_field = tk.Entry(root)
    entry_field.pack()

    button = tk.Button(root, text=&quot;Click me!&quot;, command=button_click)
    button.pack()  

    root.mainloop()
    
if __name__ == &quot;__main__&quot;:
    main()

This becomes a problem because Script1 will only have the attribute entry_field after main has been called.

It's not clear to me why you're putting this into two separate files and "importing" Script2 by calling exec on it. Why are you doing that? There are better ways of splitting up code between files, such as just doing import &lt;filename&gt;. exec should generally be used very sparingly.

答案2

得分: 1

我想传递我在script1.py中输入到输入字段的值,然后我想使用这个值并在script2.py中的标签上显示它。

不建议使用exec(open("script2.py").read())。这只是用于读取,而不是导入模块。

你不能从script2.py切换到script1.py,反之亦然,否则你的程序将冻结并且无响应。这可能需要大约15分钟或更长时间。

script1.py模块中:

使用root = tk.Tk()root.mainloop()来完全编写脚本,而不是重复。

我们可以在函数之前的顶部放置root = tk.Tk()。在这种情况下,我们可以使用root传递给任何模块。

  • button_click()函数中,只需使用import script2调用script2模块。
  • 并调用Script2.run()函数。
  • button_click()函数中删除root.mainloop()

script2.py模块中:

  • 你需要使用Toplevel来调用第二个窗口。否则,你将看不到打印输出。
  • 创建run()函数,并添加两个参数。这样我们可以从button_click()函数中调用script1模块。并声明变量core,以便将root传递给core

script1.py片段:

import tkinter as tk

root = tk.Tk()

def button_click():        
    import script2
    g = entry_field.get()
    script2.run(root, g)
  
def main():
    global entry_field
    root.title('Main Window')
     
    entry_field = tk.Entry(root)
    entry_field.pack()

    button = tk.Button(
        root,
        text="Click me!",
        command=button_click
    )
    button.pack()  

    root.mainloop()
    
if __name__ == "__main__":
    main()

script2.py

import tkinter as tk

def run(core, data):
    core = tk.Toplevel()
    core.title("Toplevel")
    label_2 = tk.Label(core, text=data)    
    label_2.pack()

屏幕截图:

如何在一个 Python 脚本中使用另一个脚本的数值。

英文:

> My idea is: I want to pass value which I typed into entry field in
> script1.py, after I want to use this value and show it with label on
> script2.py.

It is not recommended to use exec(open(&quot;script2.py&quot;).read()). It is merely to read, not import module.

You cannot swap from script2.py to script1.py and vice-versa, otherwise, you will freeze and not respond. It will take about 15 or more minutes.

On script1.py module:

Use root = tk.Tk() and root.mainloop() entirely script instead of duplicating.

We can put root = tk.Tk() at the top before the function. In that case, we can use root to pass to any modules.

  • On the button_click() function, just called script2 module using
    import script2.
  • And called Script2.run() function.
  • Remove root.mainloop() on the button_click() function.

On script2.py module:

  • You need to called second window using Toplevel. Otherwise, you
    will not see print output.
  • Create run() function, and add two parameters. In that we can call from
    button_click() script1 module. And declare variable core. So we can pass root to core.

Snippet script1.py:

import tkinter as tk


root = tk.Tk()

def button_click():        
    import Script2
    g = entry_field.get()
    Script2.run(root, g)
  
def main():
    global entry_field
    root.title(&#39;Main Window&#39;)
     
    entry_field = tk.Entry(root)
    entry_field.pack()

    button = tk.Button(
        root,
        text=&quot;Click me!&quot;,
        command=button_click
        )
    button.pack()  

    root.mainloop()
    
if __name__ == &quot;__main__&quot;:
    main()

script2.py:

import tkinter as tk
 
def run(core, data):
    core = tk.Toplevel()
    core.title(&quot;Toplevel&quot;)
    label_2 = tk.Label(core, text=data)    
    label_2.pack()

Screenshot:

如何在一个 Python 脚本中使用另一个脚本的数值。

huangapple
  • 本文由 发表于 2023年2月14日 21:03:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/75448252.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定