Python と systemd タイマーを使用して Ubuntu 上に「無限デスクトップ」を構築する

in tech

GNOME 壁紙チェンジャーの作成は、思っているよりも簡単です。実際、必要なのは Linux のデフォルトのコマンドライン テキスト エディタである nano などのターミナル テキスト エディタとタイマーだけです。 Ubuntu で作成する方法は次のとおりです。

壁紙チェンジャーを使えばデスクトップをおしゃれにできるのに、なぜ静的なデスクトップにこだわる必要があるでしょうか?

自動壁紙チェンジャーを構築することは、GNOME デスクトップをカスタマイズする楽しい方法です。壁紙を毎秒、分、時間、日、または週ごとに更新するように設定したり、アニメ、自然、風景、車などのテーマの壁紙を表示するようにカスタマイズしたりできます。そして、ここが最も重要な部分です。GNOME には、自動壁紙チェンジャーを作成するために必要なユーティリティのほとんどがすでに含まれています。早速本題に入りましょうか?

Ubuntu でのプロジェクトのサンドボックスのセットアップ

nano はほとんどの一般的な Linux ディストリビューションにプレインストールされているため、専用のプロジェクト フォルダーを作成して整理しましょう。これを行うには、GUI メソッドまたは mkdir コマンドを使用できます。フォルダーに「Wallpaper Changer Project」などの適切な名前を付けます。

mkdir -p ~/"Wallpaper Changer Project"

cd コマンドを使用してメイン プロジェクト フォルダーに移動し、mkdir コマンドを使用して「HD Wallpapers」というサブディレクトリを作成します。その後、Unsplash または別の同様の Web サイトにアクセスし、無料の HD デスクトップの壁紙を必要なだけダウンロードし、すべての画像を「HD 壁紙」フォルダーに保存します。

壁紙チェンジャーは、.jpg、.jpeg、.png の画像ファイル拡張子をサポートしています。したがって、これらのバージョンの壁紙のみをダウンロードしてください。

プロジェクトの設定は以上です。ここからは本当に楽しい作業に移りましょう。ダウンロードしたばかりのデスクトップの壁紙で動作する基本的な壁紙チェンジャーのスクリプトを作成します。

ダウンロードされたデスクトップの壁紙を処理する壁紙エンジンのコーディング

ターミナルを起動し、「Wallpaper Changer Project」フォルダーに移動し、nano を使用して「Wallpaper_changer.py」という名前の新しい Python ファイルを作成します。それが完了したら、以下のスクリプトをコピーして貼り付け、変更を保存します。

cd ~/"Wallpaper Changer Project"
nano Wallpaper_changer.py
#!/usr/bin/env python3
import os
import random
import subprocess

# ------------ CONFIGURATIONs ---------------
# Using a list makes it easier to add folders and subfolders later.
# Remember to edit the paths to match yours

WALLPAPER_DIRS = (
    "/home/htg/Wallpaper Changer Project/HD Wallpapers",
    #------------ Use absolute paths to add other wallpaper folders------------
)

def get_random_wallpaper():
    valid_extensions = ('.jpg', '.jpeg', '.png')
    all_wallpapers = ()

    for folder in WALLPAPER_DIRS:
        # ------------Check if the folder actually exists to prevent errors------------
        if os.path.exists(folder):
            for file in os.listdir(folder):
                if file.lower().endswith(valid_extensions):
                    # ------------Combine folder path and filename------------
                    all_wallpapers.append(os.path.join(folder, file))

    return random.choice(all_wallpapers) if all_wallpapers else None

def set_wallpaper(image_path): 
    uri = f"file://{image_path}"
    try:
        subprocess.run((
            "gsettings", "set", "org.gnome.desktop.background", "picture-uri", uri
        ), check=True)
        # --------- GNOME has separate settings for light and dark mode ------------
        subprocess.run((
            "gsettings", "set", "org.gnome.desktop.background", "picture-uri-dark", uri
        ), check=True)
        print(f"Success! Wallpaper set to: {image_path}")
    except subprocess.CalledProcessError as e:
        print(f"Error setting wallpaper: {e}")

if __name__ == "__main__":
    wallpaper = get_random_wallpaper()
    if wallpaper:
        set_wallpaper(wallpaper)
    else:
        print("No wallpapers found in the specified directories!")

nano では、Ctrl + O + Enter を使用してスクリプトを保存し、Ctrl + X を使用してエディタを終了します。

chmod コマンドを使用してスクリプトを実行可能にしてから実行します。

​chmod +x Wallpaper_changer.py
​./Wallpaper_changer.py

スクリプトを実行するたびに、デスクトップの壁紙がサブディレクトリ内の画像に回転するはずです。

これで、ダウンロードしたデスクトップの壁紙を操作できる基本的な壁紙チェンジャーが完成しました。しかし、オンライン画像を取得して壁紙として設定することもできるのに、なぜそこで止まる必要はありませんか?

テーマ付き壁紙用の Unsplash API との接続

壁紙チェンジャーをインターネットに接続し、ダウンロードまたは Unsplash イメージを使用してデスクトップの壁紙を更新する 50/50 の確率を適用するロジックを追加しましょう。

まず、Unsplash にログインし、次に Unsplash Developers に進みます。そこに到達したら、[あなたのアプリ]オプションを選択し、新しいアプリケーションを作成し、API 利用規約に同意し、最後にアプリケーションに名前を付けて作成し、API アクセス キーを取得します。

無料の Unsplash API には 1 時間あたり 50 リクエストの「デモモード」制限があるため、壁紙が 2 分ごとに変更されるように設定します。また、Unsplash でアプリケーションに名前を付けるときは、「壁紙」や「画像」などの単語を避けてください。画像や壁紙の変更に関係のないランダムな名前を使用します。この例では、HTG1 を使用しました。

次に、一部の GNOME ディストリビューションでは、Python が Web サーバーに接続するのに苦労する可能性があります。そのため、apt を使用して、壁紙チェンジャーが Unsplash に接続するのに役立つ Python ライブラリをインストールする必要があります。

sudo apt install python3-requests

次に、nano を使用して既存の「Wallpaper_changer.py」スクリプトを開き、以下のコードをコピーして、前のコードを置き換えるために使用します。新しいバージョンでは、ローカルの画像ファイルまたは Unsplash の画像を使用して GNOME デスクトップの壁紙を更新する可能性が 50/50 あります。

nano Wallpaper_changer.py
#!/usr/bin/env python3
import os
import random
import requests
import subprocess

# ------------ CONFIGURATIONs ---------------
# ------------Insert your Unsplash Access Key below------------
ACCESS_KEY = "YOUR_UNSPLASH_ACCESS_KEY_GOES_HERE"

# ------------Edit the directory path to match yours------------
LOCAL_DIR = "/home/htg/Wallpaper Changer Project/HD Wallpapers"

# ------These are the Unsplash API settings. Update the query to any wallpaper theme------
API_URL = f"https://api.unsplash.com/photos/random?client_id={ACCESS_KEY}&orientation=landscape&query=space,galaxy"

def set_wallpaper(image_path):
    """Sets the wallpaper for both Light and Dark modes in Ubuntu GNOME."""
    uri = f"file://{image_path}"
    schemas = ("picture-uri", "picture-uri-dark")
    for key in schemas:
        subprocess.run(("gsettings", "set", "org.gnome.desktop.background", key, uri))

def get_web_wallpaper():
    save_path = os.path.join(LOCAL_DIR, "web_latest.jpg")
    try:
        response = requests.get(API_URL, timeout=10)
        if response.status_code == 200:
            data = response.json()
            print(f"(Link) View this wallpaper at: {data('links')('html')}")
            image_url = data('urls')('raw') + "&w=1920&h=1080&fit=crop"
            img_data = requests.get(image_url, timeout=15)
            with open(save_path, 'wb') as f:
                f.write(img_data.content)
            return save_path
    except Exception as e:
        print(f"API/Web Error: {e}")
    return None

def main():
    # ------------This verifies the directory exists before proceeding------------
    if not os.path.exists(LOCAL_DIR):
        print(f"Error: Could not find folder at {LOCAL_DIR}")
        print("Make sure this script is saved INSIDE the 'Wallpaper Changer Project' folder.")
        return

    # ------------ This is the logic for the 50/50 probability------------
    if random.random() > 0.5:
        print("(Cloud) Fetching a fresh image from Unsplash...")
        wallpaper = get_web_wallpaper()
    else:
        wallpaper = None

    if not wallpaper:
        print("(Local) Picking a favorite from your folder...")
        files = (os.path.join(LOCAL_DIR, f) for f in os.listdir(LOCAL_DIR) 
                 if f.lower().endswith(('.jpg', '.png', '.jpeg')))
        wallpaper = random.choice(files) if files else None

    if wallpaper:
        set_wallpaper(wallpaper)
        print(f"Success! Desktop updated to: {os.path.basename(wallpaper)}")

if __name__ == "__main__":
    main()

コードをコピーして貼り付けた後、chmod を使用してファイルを実行可能にし、テストします。

chmod +x Wallpaper_changer.py
./Wallpaper_changer.py

壁紙チェンジャーは 50/50 ロジックを使用して、ダウンロードされた画像または Unsplash イメージのいずれかでデスクトップの壁紙を更新する必要があります。 Unsplash に接続できない場合は、ダウンロードしたイメージに戻ります。

Systemd を使用して壁紙変更を自動化する

Systemd は自動化の魔法が起こる場所です。ターミナルを開き、nano を使用して新しい systemd サービス ユニットを作成します。

​sudo nano /etc/systemd/system/wallpaper-changer.service

次の設定をそこに貼り付けます。どのプログラムを実行するか、誰が実行しているか、Python がどこにあるかをコンピューターに指示します。

(Unit)
Description= Wallpaper Changer Project
# ---This tells the script to wait for an internet connection before trying Unsplash---
After=network-online.target
Wants=network-online.target

(Service)
Type=oneshot
# ----- Edit this to match the full path to Python, your script, and username-----
ExecStart=/usr/bin/python3 "/home/htg/Wallpaper Changer Project/Wallpaper_changer.py"
User=htg
# ------------ This environment variable lets Python talk to the GNOME Desktop
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus

(Install)
WantedBy=multi-user.target

1000 は、Ubuntu で作成された最初のユーザーのデフォルトです。ユーザー ID が不明な場合は、ターミナルで id -u を実行してください。その番号が異なる場合 (1001 など)、DBUS 行を更新しますが、壁紙チェンジャーが失敗する可能性があることに注意してください。

nano ショートカットを使用してサービス ユニットを保存し、終了します。再度 nano を使用してタイマー ユニットを作成します。

​sudo nano /etc/systemd/system/wallpaper-changer.timer

次の設定をコピーして貼り付け、保存して終了します。

(Unit)
Description=Trigger Wallpaper Changer every 2 minutes

(Timer)
# -----Sets the timer to run 1 minute after boot up-----
OnBootSec=1min
# -----Sets the timer to run every 2 minutes after boot up-----
OnUnitActiveSec=2min
# -----Ensures the timer remains persistent and triggers when the computer wakes up-----
Persistent=true

(Install)
WantedBy=timers.target

残っている唯一のことは、デーモンをリロードしてタイマーを有効にして開始することによってタイマーをアクティブにすることです。

sudo systemctl daemon-reload
sudo systemctl enable --now wallpaper-changer.timer

タイマーにより、2分ごとに壁紙が自動的に変更されます。ステータスをチェックするか、journalctl を使用してログを表示することによって、動作していることを確認することもできます。

systemctl list-timers –all | grep wallpaper
journalctl -u wallpaper-changer.service -f
systemd のロゴと、前にラップトップを使用している Linux マスコット。

私が最終的に Cron を捨てて Ubuntu で Systemd タイマーを使用する理由

なぜ基本的な時間ベースのトリガーにこだわるのでしょうか? Systemd タイマーは、より優れたロギング、依存関係管理を提供し、「起動後 1 分」にスクリプトを実行できます。


これで、ダウンロードした、またはテーマを設定した Unsplash 画像で GNOME デスクトップの壁紙を更新する自動壁紙チェンジャーが正常に作成されました。

関連記事

前の投稿
パスワードと非表示の行ではデータは保存されませんが、これによりデータが保存されます。
次の投稿
今週観るべき Prime Video の必見映画 5 本 (2 月 9 日)