pyvirtualdisplay

repository·master·Indexed 21 days ago

https://github.com/ponty/pyvirtualdisplay

A Python wrapper for X Window System virtual framebuffers such as Xvfb, Xephyr, and Xvnc. It is used for headless GUI testing, automated screenshots, and running GUI applications without a physical monitor. Features include a Display context manager, a SmartDisplay submodule for capturing Pillow Image screenshots, and support for custom resolutions, color depth, and backend selection.

Tokens
1.4K
Snippets
6
Records
6
Agent score
23%

What's inside pyvirtualdisplay

  1. Enable thread-safe operation

    master

    By default, pyvirtualdisplay is not thread-safe because it modifies the global os.environ["DISPLAY"] variable.

    To use multiple displays in different threads, you must:

    1. Set manage_global_env=False in the Display (or SmartDisplay) constructor.
    2. Manually pass the display environment variables to your child processes using disp.env().
    import threading
    from pyvirtualdisplay.smartdisplay import SmartDisplay
    from easyprocess import EasyProcess
    
    def thread_function(index):
        # manage_global_env=False prevents modifying os.environ globally
        with SmartDisplay(manage_global_env=False) as disp:
            cmd = ["xmessage", str(index)]
            # Use disp.env() to provide the correct DISPLAY to the process
            with EasyProcess(cmd, env=disp.env()):
                img = disp.waitgrab()
                img.save(f"xmessage{index}.png")
    
    t1 = threading.Thread(target=thread_function, args=(1,))
    t2 = threading.Thread(target=thread_function, args=(2,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
  2. Install pyvirtualdisplay and its dependencies

    master

    Install the core package via pip:

    python3 -m pip install pyvirtualdisplay

    Optional Dependencies

    • Pillow: Required for the smartdisplay submodule to handle screenshots.
      python3 -m pip install pillow
    • EasyProcess: Used in many of the project's examples.
      python3 -m pip install EasyProcess

    System Dependencies (Ubuntu 22.04)

    To use all backends (Xvfb, Xephyr, Xvnc) and run examples, install the following system packages:

    sudo apt-get install xvfb xserver-xephyr tigervnc-standalone-server x11-utils gnumeric
    python3 -m pip install pyvirtualdisplay pillow EasyProcess

    Note: The selected backend (Xvfb, Xephyr, or Xvnc) must be installed on your system and available in your PATH before pyvirtualdisplay can start it.

    $ python3 -m pip install pyvirtualdisplay
  3. Configure Display backends and settings

    master

    You can customize the Display constructor to select specific backends, window visibility, resolution, and color depth.

    Backend Selection

    • Xvfb (Default/Headless): Display(backend="xvfb") or Display(visible=False)
    • Xephyr (Visible/Nested): Display(backend="xephyr") or Display(visible=True)
    • Xvnc (VNC access): Display(backend="xvnc")

    Display Configuration

    • Size: Set resolution using size=(width, height).
    • Color Depth: Set depth using color_depth=bits.
    • Background Color: Set background using bgcolor="color_name" (useful for Xephyr).
    • Xauthority: Enable Xauthority file generation with use_xauth=True (requires xauth installed on the system).
    # Examples of different configurations
    disp = Display(backend="xvfb")
    disp = Display(visible=True)
    disp = Display(backend="xvnc")
    disp = Display(size=(100, 60))
    disp = Display(color_depth=24)
  4. Use the Display class as a context manager

    master

    The recommended way to control a virtual display is using the Display class as a context manager. This ensures the display is automatically stopped when the block exits.

    When a display is active, disp.is_alive() returns True. Once stopped, it returns False and the DISPLAY environment variable is restored to its original value.

    from pyvirtualdisplay import Display
    with Display() as disp:
        # display is active
        print(disp.is_alive()) # True
    # display is stopped
    print(disp.is_alive()) # False
  5. Pass extra arguments to Xvfb

    master

    You can pass additional command-line arguments directly to the Xvfb backend using the extra_args parameter. For example, to disable the mouse cursor in Xvfb, use ["-nocursor"].

    from pyvirtualdisplay import Display
    
    with Display(backend="xvfb", extra_args=["-nocursor"]):
        # your code here
        pass
  6. Take screenshots with SmartDisplay

    master

    The smartdisplay submodule provides the SmartDisplay class, which is an extension of Display. It includes a waitgrab() method that polls the virtual display until content is rendered and then returns a screenshot as a Pillow Image object.

    Note: This requires the Pillow library to be installed.

    from pyvirtualdisplay.smartdisplay import SmartDisplay
    
    with SmartDisplay() as disp:
        # ... run your GUI application ...
        # wait until something is displayed and take a screenshot
        img = disp.waitgrab()
        img.save("screenshot.png")