简体   繁体   English

当将简短的Python脚本作为函数隔离时,为什么运行方式不同?

[英]Why does short Python script run differently when it's isolated as a function?

As part of a program that hits some points on a particular web interface, this component enables the user to click three spots & writes a config file that instructs the program precisely where to put the cursor each time it runs. 作为在特定Web界面上命中某些点的程序的一部分,此组件使用户可以单击三个点并编写一个配置文件,该文件指示该程序每次运行时将光标精确放置在何处。 These lines work as intended (Python 3.6) when they're in the main body of the program; 这些行在程序的主体中时按预期的方式工作(Python 3.6); the problem is, I want to isolate them as a function so I can enable the user to choose whether to reconfigure or not. 问题是,我想将它们隔离为一个功能,以便使用户能够选择是否重新配置。 (If user hasn't switched browsers nor resized, existing config file is fine.) (如果用户没有切换浏览器或调整大小,则可以使用现有的配置文件。)

I hope a knowledgeable Pythonista can help me understand why simply indenting these lines beginning with window=Tk() four/eight spaces as appropriate and putting them in a function causes them to not run properly, instead hanging up in the middle of the first call to on_click. 我希望知识渊博的Pythonista可以帮助我理解为什么仅在适当的位置缩进以window = Tk()开头的四行/八行并将这些行放入函数中会导致它们无法正常运行,而是挂在第一次调用的中间到on_click。 (Edit: The error message from terminal is below the script) (编辑:来自终端的错误消息在脚本下方)

import threading, pynput, os, configparser
from pynput.mouse import Listener
from tkinter import *
configfile_name = "config.ini"
cfg = configparser.ConfigParser()

def write_config(x_coord, y_coord):
   global configfile_name
   c = open(configfile_name, "a", encoding="utf-8")
   c.write('x=' + x_coord + '\r')
   c.write('y=' + y_coord)
   c.write('\r\n')
   c.close()

def write_first_section(section_name):
   global configfile_name
   c = open(configfile_name, "w", encoding="utf-8")
   c.write('[' + section_name + '] \r')
   c.close()

def write_section(section_name):
   global configfile_name
   c = open(configfile_name, "a", encoding="utf-8")
   c.write('[' + section_name + '] \r')
   c.close()

def on_click(x, y, button, pressed) :
   global count, window, listener
   write_config(str(x), str(y))
   window.after(2000, window.destroy)    
   listener.stop()  

window = Tk()
window.title("Map your screen")
window.geometry('350x80+300+225')
window.lift()
write_first_section('tab')
lbl = Label(window, text="With the QP chat interface screen up,\nclick the 'New' tab at upper left above the blue bar")
lbl.grid(column=0, row=0)
with Listener(on_click=on_click) as listener:
   window.mainloop()
   listener.join()
listener.stop()
write_section('pickup')
window = Tk()
window.title("Step two!")
window.geometry('350x80+300+225')
window.lift()
lbl = Label(window, text="Now, click just below the blue bar")
lbl.grid(column=0, row=0)
with Listener(on_click=on_click) as listener:
   window.mainloop()
   listener.join()
listener.stop()
write_section('paste')
window = Tk()
window.title("Step three!")
window.geometry('350x80+300+225')
window.lift()
lbl = Label(window, text="Lastly, click in the text box")
lbl.grid(column=0, row=0)
with Listener(on_click=on_click) as listener:
   window.mainloop()

When placed in a function, script throws these errors: 当放置在函数中时,脚本会引发以下错误:

Unhandled exception in listener callback
Traceback (most recent call last):
  File "/home/bruce/.local/lib/python3.6/site-packages/pynput/_util/__init__.py", line 157, in inner
    return f(self, *args, **kwargs)
  File "/home/bruce/.local/lib/python3.6/site-packages/pynput/_util/xorg.py", line 458, in _handler
    self._handle(self._display_stop, event)
  File "/home/bruce/.local/lib/python3.6/site-packages/pynput/mouse/_xorg.py", line 141, in _handle
    self.on_click(px, py, self._button(event.detail), True)
  File "/home/bruce/.local/lib/python3.6/site-packages/pynput/_util/__init__.py", line 78, in inner
    if f(*args) is False:
  File "does_it_all.py", line 37, in on_click
    window.after(2000, window.destroy)
NameError: name 'window' is not defined
Traceback (most recent call last):
  File "does_it_all.py", line 231, in <module>
    map()
  File "does_it_all.py", line 192, in map
    listener.join()
  File "/home/bruce/.local/lib/python3.6/site-packages/pynput/_util/__init__.py", line 205, in join
    six.reraise(exc_type, exc_value, exc_traceback)
  File "/home/bruce/.local/lib/python3.6/site-packages/six.py", line 692, in reraise
    raise value.with_traceback(tb)
  File "/home/bruce/.local/lib/python3.6/site-packages/pynput/_util/__init__.py", line 157, in inner
    return f(self, *args, **kwargs)
  File "/home/bruce/.local/lib/python3.6/site-packages/pynput/_util/xorg.py", line 458, in _handler
    self._handle(self._display_stop, event)
  File "/home/bruce/.local/lib/python3.6/site-packages/pynput/mouse/_xorg.py", line 141, in _handle
    self.on_click(px, py, self._button(event.detail), True)
  File "/home/bruce/.local/lib/python3.6/site-packages/pynput/_util/__init__.py", line 78, in inner
    if f(*args) is False:
  File "does_it_all.py", line 37, in on_click
    window.after(2000, window.destroy)    
NameError: name 'window' is not defined

When I try putting everything after the on_click(....) function definition into a function called map(), and then try to run map(), it hangs up after writing [tab] into the config.ini file, leaving the first window stuck on the screen. 当我尝试将on_click(....)函数定义之后的所有内容放入一个名为map()的函数中,然后尝试运行map()时,在将[tab]写入config.ini文件后,它将挂起,第一个窗口停留在屏幕上。 But when I run it as written above, it properly progresses through all three windows and writes all three parts of the config file. 但是,当我如上所述运行它时,它会在所有三个窗口中正常运行并写入配置文件的所有三个部分。 I'm sure there are terrible blunders in the script, but nevertheless: Why is it those 32 lines would run fine when out in the open, but break when they comprise a function? 我确定脚本中存在严重的错误,但是:为什么为什么这32行在开放时运行良好,而在包含函数时就中断了呢? Thanks for any help and constructive scolding! 感谢您的帮助和建设性的指责!

When you moved those lines into a function, the window (and listener ) variables you defined stopped being global variables, and became local to that function. 当您将这些行移动到函数中时,您定义的window (和listener )变量不再是全局变量,而成为该函数的局部变量。 Your on_click functions was relying on window (and listener ) to be defined globally, and since they no longer existed as globals at all, your code broke. 您的on_click函数依赖于window (和listener )进行全局定义,并且由于它们根本不再作为全局变量存在,因此您的代码中断了。

The minimal fix would be to add: 最小的解决方法是添加:

global window, listener

to the top of your new function, so it treats window and listener as global variables, rather than the default behavior of treating them as locals. 到新函数的顶部,因此它将windowlistener视为全局变量,而不是将它们视为局部变量的默认行为。

A more thorough solution would be to write a class where window and listener (and possibly other things) were instance attributes, accessed via self , with your new function and on_click being methods of that class. 一个更彻底的解决方案是编写一个类,其中windowlistener (可能还有其他东西)是实例属性,可以通过self访问,而您的新函数和on_click是该类的方法。 It's not critical in this case, but any time you find yourself reliant on global for mutable global state, it's usually a bad design, and you really wanted a class in the first place. 在这种情况下并不重要,但是任何时候只要您发现自己依赖global变量来获取可变的全局状态,通常这都是一个糟糕的设计,并且您确实真的想在第一堂课。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么 python 脚本在 pycharm 中运行和在命令提示符下运行时的行为不同? - Why does a python script behaves differently when it is run in pycharm and when it is run from a command prompt? 为什么Windows 10 Task Scheduler执行我的Python脚本时会产生不同的运行 - Why does my Python script run differently when executed by Windows 10 Task Scheduler 为什么 python 控制台运行与空闲不同 - why does python console run differently to idle 计划的 cron Python 脚本日志记录的工作方式与手动运行时不同 - Scheduled cron Python script logging working differently than it does when run manually 为什么我的python类方法本身的行为与我运行模块时的行为不同? - Why does my python class method behave differently by itself than when I run the module? 现在,python的print函数处理unicode的方式与编写Dive Into Python时的方式不同吗? - Does python's print function handle unicode differently now than when Dive Into Python was written? 为什么运行 Python 脚本时 Win 7 会发出哔哔声? - Why does Win 7 make a beep when I run a Python script? 为什么 Python 中的以下简短脚本会忽略“if”中的条件? - Why does the following short script in Python disregard the condition in "if"? 为什么python脚本在Spyder vs cmd提示符下的工作方式不同 - Why does python script works differently in Spyder vs cmd prompt 为什么我的 python 脚本在 temal 和 cron 之间的工作方式不同? - Why does my python script work differently between the teminal and cron?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM