Script works under Python 3.5.2, but not under 3.12.3

I’m using a [script] program that works under Python 3.5.2, but not under 3.12.3. From my research, subprocess.check_output() was changed in the 3.12.3 library, and the syntax differs from earlier versions. I program in many languages, but not Python, where I’m a total zero. I use Ubuntu, and recently updated to version 24.04. In this new OS release, Python was upgraded to 3.12.3, which broke my program.

This script is supposed to run in the background on Ubuntu as a “Startup” program. It’s purpose is to allow a “grid” view of the files in folders I select, while other folders are the regular “list” view. The folder view cannot be set on a folder-by-folder basis. This script resolves that issue.

Oddly, under Ubuntu 24.04, the startup script won’t start. However, I can open an terminal window and invoke the program manually where it may run for a few minutes, or error out immediately. Ultimately, errors cause the program to stop running.

Here is the code I believe generates errors under 3.12.3, but worked perfectly with 3.5.2:
pid = subprocess.check_output([“pidof”, “nautilus”]).decode(“utf-8”).strip()

I’d like to know how (or what) to change in the above program make it compatible with 3.12.3. Also, I don’t want to risk downgrading to an earlier version of Python lest it affect something else in the operating system.

One more detail: The program won’t start using the “Startup Programs”, but WILL run (sort of, with errors) if run manually from a terminal window. Everything was ported from an earlier version of Ubuntu. All permissions and paths have been checked.

Here is the entire program:

#!/usr/bin/env python3
import subprocess
import time
import os
wlist = os.environ["HOME"]+"/.window_list.txt"


def get(cmd):
    try:
        return subprocess.check_output(cmd).decode("utf-8")
    except subprocess.CalledProcessError:
        return ""


def check_window():
    pid = subprocess.check_output(["pidof", "nautilus"]).decode("utf-8").strip()
    wlist = get(["wmctrl", "-lp"]).splitlines()
    front = get(["xdotool", "getactivewindow", "getwindowname"]).strip()
    return (front, [w for w in wlist if all([pid in w, front in w])])


match1 = check_window()


while True:
    time.sleep(1)
    match2 = check_window()
    if all([match2 != match1, match2[1] != []]):
        w = match2[0]
        try:
            if w in open(wlist).read().splitlines():
                cmd = "xdotool key Ctrl+2"
                subprocess.Popen(["/bin/bash", "-c", cmd])
            else:
                cmd = "xdotool key Ctrl+1"
                subprocess.Popen(["/bin/bash", "-c", cmd])
        except FileNotFoundError:
            pass
    match1 = match2

----
Example of the errors:

XGetWindowProperty[_NET_ACTIVE_WINDOW] failed (code=1)
xdo_get_active_window reported an error

pidof: can't read from 100934/stat

Assistance appreciated.  Thanks!

Dan

Your example of one of the errors is:

pidof: can't read from 100934/stat

check_window is starting pidof, but that’s sometimes encountering an error for some reason, and that failure is making check_window fail, which, in turn, terminates the script.

I don’t think that Python has anything to do with why pidof is failing.

Maybe it’s a race condition and pidof can’t always read because something else is updating what it’s reading.

You could try modifying check_window to sleep a short time and then try again if pidof fails.

Another point: all([match2 != match1, match2[1] != []]) looks strange. Why that instead of match2 != match1 and match2[1] != []? Similarly, why all([pid in w, front in w]) instead of pid in w and front in w?

Matthew,
Per my original post, I’m fluent in several programming languages, but zero in Python. This script was posted for public use on a Linux BBS about 9 years ago. It performed a task that I wanted, so I downloaded and installed it on a test computer (for safety purposes). It worked as claimed, so I put it on my main computers. This was 9 years and several operating system updates ago. With my recent update to Ubuntu 24.04, which comes with Python 3.12.3, this script no longer works. It’s functioned flawlessly for the past 9 years on systems with earlier versions of Python.

Unfortunately, I don’t know Python at all, and subsequently am not able to answer your questions. I was hoping someone with the requisite skills in Python could suggest the necessary changes to make it compatible with 3.12.3.

In my research for the differences between Python 3.5.2 and 3.12.3, I found a site that defined syntax differences in the use of subprocess.check_output() that were implemented for that function starting in 3.12.3 compared to earlier versions of Python. If there are other changes between 3.5.2 and 3.12.3, I’ve not researched any deeper than for “check_output()”.

If I understand correctly, you updated Ubuntu, which came with a new version of Python.

So, 2 things changed: the version of Ubuntu, and the version of Python.

The errors you’ve shown don’t appear to come from Python itself, but from the commands that you’re running from Python, so I don’t think that it’s the version of Python or the script that’s the problem.

I think something in Ubuntu changed since the previous version you were using.

You’re correct. There were two concurrent changes; Operating system and Python. This could not be prevented. Python 3.12.3 came packaged with Ubuntu 24.04. I know Linux fairly well. Python not at all. This lack of knowledge about Python is what prompted me to reach out for assistance. Essentially, I’m trying to determine if a syntax difference for this function exists between 3.5.2 and 3.12.3 that could cause this? Info I found on this website (The Python Standard Library — Python 3.13.2 documentation) leads me to believe that’s the case, but I don’t know how to resolve it by amending the existing code. I don’t want to risk trying to install an older version of Python out of concern it could cause other problems.

Python is easy to learn the basica of given you are an experienced programmer. You should be able to speed read a python tutorial in less then an hour.

As for the problem with pidof. I would debug this from the command line. You can run the logic of the pidof and xpotool command to see what is happening.

Oh I wonder if the script depends on X11 and your desktop is now wayland?

What is it try to do?

Based on the errors you’re getting, the problem is almost certainly that Ubuntu moved to Wayland instead of X by default. The error you’re seeing looks like it came from the front = get(["xdotool", "getactivewindow", "getwindowname"]).strip() line in check_window(), since it mentions XGetWindowProperty[_NET_ACTIVE_WINDOW] failed. That makes sense, because that’s the first call to xdotool in the script, which, as the name implies, is for X only.

Unfortunately, the script can’t easily be updated to work on Wayland. Getting the current active window on Wayland is a hard problem, by design.

If this is really important to get working, the easiest thing would be to switch back to X for now. You could at least try that, to make sure that this is actually the problem. Otherwise, maybe you could find a Nautilus extension that does what you want?

You’re correct. In Ubuntu 24.04, Wayland is the default display server over X11.

However, I’m running X11 as confirmed by this command entered into the terminal:
echo "$XDG_SESSION_TYPE

It returns “X11”.

In the interim since my original post, I’ve become aware of a manual shortcut that performs this function: Control + 1 and Control + 2. The latter toggles a folder into a grid view. The former toggles it back. With the script, this was automated, and affected only the folders I’d selected. All others had the “normal” (list) view.

Downside to the manual method, when a particular view is selected, it impacts all folders whether they’re open or not. Changing the view for one folder changes all folders. While this isn’t a big problem, it means I can’t have two folders open with different views at the same time. This isn’t an issue when only a few sub-folders or files exist within the selected folder, but it’s a hassle when there are many folders and/or files in the second or subsequent folders I may have open and visible on the screen at the same time (such as for purposes of copying/moving from one folder to another).

The more I dig into this, the more It’s becoming evident I’ll have to live with the situation for now and use the manual toggle method. Inconvenient and irritating, but workable if I tolerate it.

Dan

It is strange that it’s failing, if you are still using X. Perhaps something else in xdotool broke with the update?

An alternative option is to use a different file manager that does support setting a default view per folder. I’ve seen Nemo recommended for that purpose, although that was a long time ago. Maybe it will work for you? How to Install and Make Nemo the Default File Manager in Ubuntu

Here’s the script with a little more error trapping:

#!/usr/bin/env python3
import subprocess
import time
import os

wlist = os.environ["HOME"] + "/.window_list.txt"

def get(cmd):
    try:
        return subprocess.check_output(cmd).decode("utf-8")
    except subprocess.CalledProcessError:
        return ""

def check_window():
    try:
        pid = subprocess.check_output(["pidof", "nautilus"]).decode("utf-8").strip()
        wlist = get(["wmctrl", "-lp"]).splitlines()
        front = get(["xdotool", "getactivewindow", "getwindowname"]).strip()
        return (front, [w for w in wlist if pid in w and front in w])
    except subprocess.CalledProcessError:
        return ("", [])

match1 = check_window()

while True:
    time.sleep(1)
    match2 = check_window()

    if match2 != match1 and match2[1] != []:
        w = match2[0]

        try:
            if w in open(wlist).read().splitlines():
                cmd = "xdotool key Ctrl+2"
                subprocess.Popen(["/bin/bash", "-c", cmd])
            else:
                cmd = "xdotool key Ctrl+1"
                subprocess.Popen(["/bin/bash", "-c", cmd])
        except FileNotFoundError:
            pass

    match1 = match2

I don’t have the depth of knowledge required to delve that extensively into xdotool or other packages in search of the cause of (and correction for) this issue.

Reports related to replacing Nautilus with Nemo are mixed, with experiences ranging from good to horrible. Most appear to be dated, however.

That said, your suggestion about Nemo is duly noted. I’ve just found information applicable to installing Nemo on 24.04, and will try it on a backup computer when my time allows.

Thanks!

Older Python modules or routines may not be compatible with newer Python. This is why when you update Python you have to update your old apps as well, so that means allocating time and money to do so. This also means changing all your paths to look at the new Python and new modules, if the new and old Python are on the same machine.

Also be aware that on Windows there is a program installed in c:\windows\py.exe (on my system) which points to the most recent python you installed. Make sure that gets updated as well.

My advice: update Python, the modules, and get your apps to run on the new Python. Yet it takes time but it’s worth it.

Source: We did everything in Perl for 20 years and now Perl is dead, very dead, and unsupported with forums. People are just moving to other languages like Python and I understand Python is just more secure and can do more things more easily and generally with fewer lines of code.

I’m not understanding how your reply is related to the OPs issues.

Overall it might be better for OP to upgrade their Python as a starting point. When doing older Python tutorial with a newer Python installed I found some problems. For example, some modules worked in the older Python, but did not work in a newer python. Just a suggestion. Because I’ve found similar problems.

The issue is not python but Wayland vs. X11 and upgraded tools.

The script I’m using is several years old. It has worked perfectly under previous versions of Ubuntu until 24.04. Ubuntu 24.04 includes Python 3.12.3 as part of the installation. Downgrading Python isn’t an option because some aspects of the operating system rely on Python. Changing to an older version of Python may break features in the OS.

So, I’m using Ubuntu 24.04.2, and Python 3.12.3. In reference to Chuck’s suggestion about upgrading Python … it has already been upgraded. I had previously been using Python 3.5.2 with my previous version of Ubuntu.

Could something in Ubuntu 24.04 itself cause my script to fail? Possibly. However, my early research indicates at least some fault may be with Python. A description of the subprocess module at the following link indicates changes were made in the 3.12.3 library for this function:

and has been working perfectly until Ubuntu 24.04, which included Python 3.12.3.

I have confirmed Ubuntu on my computer is running X11, not Wayland.

Is this a show-stopper? No. It’s a convenience feature that makes life easier. However, it can be manually accommodated as long as I keep a recent copy of my Book of Bad Words at hand for when I have to use my keyboard and switch between grid and list views.

It’s been suggested I do some serious studying to learn Python. I have an engineering firm to run, and my time at this juncture is very limited. I was hoping to find someone with sufficient knowledge of Python to re-write the suspect line in the script to make it compatible with 3.12.3 and still do the same job.

The script I’m using originated at this link:

There are three modules at the above link. Modules under steps 1 and 2 work without problems. The “Set View” module in step 3 generates errors. This is the line that appears to be the source:

pid = subprocess.check_output(["pidof", "nautilus"]).decode("utf-8").strip()

This module is also stated as changed in 3.12.3.

It’s also been suggested I replace Nautilus with Nemo, the latter of which appears to be able to adjust views for each individual folder. I’ve also read mixed reviews about Nemo that give me pause to install it, wherein the cure may be worse than the disease (so to speak). Changes of that nature seem to follow the Law of Unintended Consequences, where a particular problem is addressed, but new issues are created in the process.

Dan