2
\$\begingroup\$

I wrote a small script that opens a window using PyQt when a specific file gets created.

This is to let me know when another program (that I have no control over) has finished calculating something. I know at the end of the calculation a specific file is created.

Here is the code:

from PyQt5.QtWidgets import QWidget, QLabel
import os.path

file_to_check = "D:/test.txt"

alert_widget = QWidget()
alert_widget.setWindowTitle("Program X finished")
done_label = QLabel("Done",alert_widget)
done_label.move(50,50)

file_does_not_exist = True

while file_does_not_exist:
    if os.path.isfile(file_to_check):
        file_does_not_exist = False

alert_widget.show()

The widget that gets shown luckily just pops up in front of whatever window im currently active in, whether it's browsing the internet or working on an excel sheet. That is intended behaviour, but I did not write it in by specifying it as a "top level" window or somehting.

The script is started in an IPython console in Spyder and just left to run there. It works exactly as expected.

Now my questions

  • is this constantly running loop good practice?
  • are there any downsides to having that loop constantly running in the background?
  • could it block other programs?
  • is there another, more elegant way to achieve what I'm looking to do?
  • is the code following python coding conventions?
\$\endgroup\$
5
  • 3
    \$\begingroup\$ Useful hint: How to check in python that a file in a folder has changed?. \$\endgroup\$ – Toby Speight Feb 28 '19 at 13:57
  • \$\begingroup\$ @Toby, thanks for the link, I'll try the inotify for python module. However, even using that as I understand it I would still have a constantly running for loop. In that case would there be any advantage using that module? Might be a bit of an overkill maybe, when os.path.isfile gets the job done as well. \$\endgroup\$ – Freya W Mar 1 '19 at 9:32
  • 1
    \$\begingroup\$ Yes, there's an advantage, because inotify waits for a change, rather than busy-looping. So you're being kinder to other processes and to your power consumption. I could write that as an answer if you'd like. \$\endgroup\$ – Toby Speight Mar 1 '19 at 10:34
  • \$\begingroup\$ @Toby, it seems that inotify does not run on Windows. I have found the watchdog module instead, which I am now using for another script. \$\endgroup\$ – Freya W Mar 1 '19 at 10:35
  • \$\begingroup\$ @Toby, yes, even though inotify does not work for me, the fact that I should use a module that doesn't busy loop is still worth an answer! \$\endgroup\$ – Freya W Mar 1 '19 at 10:36
2
\$\begingroup\$

The variable file_does_not_exist is simply used as loop control, but we don't need it:

while not os.path.isfile(file_to_check):
    pass

However, this loop is very inefficient. It's what we call a busy loop; that is, it never pauses, but continually polls for its condition. This is harmful, as it monopolises a processor and wastes energy. Sensible operating systems will de-prioritise busy tasks like this (to reduce its impact on other processes), which will reduce the UI responsiveness when you exit the loop, until the scheduler catches up with the change in the program's behaviour.

Instead, we should use operating system features (preferably abstracted in a platform-independent Python library) to wait for a change, allowing your process to sleep until it's notified. I don't know of a platform-independent library, but there are some possibilities for Linux (inotify) and Windows (watchdog) at least. Using one of these will yield processor time to other processes and make your program into a "good citizen" on a shared system.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.