pyvirtualdisplay is a python wrapper for Xvfb, Xephyr and Xvnc
Links:
Features:
Possible applications:
- headless run
- GUI testing
- automatic GUI screenshot
install the program:
$ python3 -m pip install pyvirtualdisplay
optional: pyscreenshot and Pillow should be installed for smartdisplay
submodule:
$ python3 -m pip install pyscreenshot pillow
on Ubuntu:
$ sudo apt-get install xvfb xserver-xephyr vnc4server xfonts-base
$ python3 -m pip install pyvirtualdisplay pyscreenshot pillow
Controlling the display with start()
and stop()
methods:
from pyvirtualdisplay import Display
disp = Display().start()
# display is active
disp.stop()
# display is stopped
After Xvfb display is activated "DISPLAY" environment variable is set for Xvfb.
(e.g. os.environ["DISPLAY"] = :1
)
After Xvfb display is stopped "DISPLAY" environment variable is restored to its original value.
Controlling the display with context manager:
from pyvirtualdisplay import Display
with Display() as disp:
# display is active
pass
# display is stopped
Selecting Xvfb backend:
disp=Display()
# or
disp=Display(visible=False)
# or
disp=Display(backend="xvfb")
Selecting Xephyr backend:
disp=Display(visible=True)
# or
disp=Display(backend="xephyr")
Selecting Xvnc backend:
disp=Display(backend="xvnc")
Setting display size:
disp=Display(size=(100, 60))
Setting display color depth:
disp=Display(color_depth=24)
The display is hidden.
If visible=True
then a nested Xephyr window opens and the GUI can be controlled.
# pyvirtualdisplay/examples/headless.py
"Start Xvfb server. Open xmessage window."
from easyprocess import EasyProcess
from pyvirtualdisplay import Display
with Display(visible=False, size=(100, 60)) as disp:
with EasyProcess(["xmessage", "hello"]) as proc:
proc.wait()
The same as headless example, but it can be controlled with a VNC client.
# pyvirtualdisplay/examples/vncserver.py
"Start virtual VNC server. Connect with: vncviewer localhost:5904"
from easyprocess import EasyProcess
from pyvirtualdisplay import Display
with Display(backend="xvnc", size=(100, 60), rfbport=5904) as disp:
with EasyProcess(["xmessage", "hello"]) as proc:
proc.wait()
Run it:
$ python3 -m pyvirtualdisplay.examples.vncserver
Check it with vncviewer:
$ vncviewer localhost:5904
# pyvirtualdisplay/examples/lowres.py
"Testing gnumeric on low resolution."
from easyprocess import EasyProcess
from pyvirtualdisplay import Display
# start Xephyr
with Display(visible=True, size=(320, 240)) as disp:
# start Gnumeric
with EasyProcess(["gnumeric"]) as proc:
proc.wait()
Run it:
$ python3 -m pyvirtualdisplay.examples.lowres
Image:
# pyvirtualdisplay/examples/screenshot.py
"Create screenshot of xmessage in background using 'smartdisplay' submodule"
from easyprocess import EasyProcess
from pyvirtualdisplay.smartdisplay import SmartDisplay
# 'SmartDisplay' instead of 'Display'
# It has 'waitgrab()' method.
# It has more dependencies than Display.
with SmartDisplay() as disp:
with EasyProcess(["xmessage", "hello"]):
# wait until something is displayed on the virtual display (polling method)
# and then take a fullscreen screenshot
# and then crop it. Background is black.
img = disp.waitgrab()
img.save("xmessage.png")
Run it:
$ python3 -m pyvirtualdisplay.examples.screenshot
Image:
# pyvirtualdisplay/examples/nested.py
"Nested Xephyr servers"
from easyprocess import EasyProcess
from pyvirtualdisplay import Display
with Display(visible=True, size=(220, 180), bgcolor="black"):
with Display(visible=True, size=(200, 160), bgcolor="white"):
with Display(visible=True, size=(180, 140), bgcolor="black"):
with Display(visible=True, size=(160, 120), bgcolor="white"):
with Display(visible=True, size=(140, 100), bgcolor="black"):
with Display(visible=True, size=(120, 80), bgcolor="white"):
with Display(visible=True, size=(100, 60), bgcolor="black"):
with EasyProcess(["xmessage", "hello"]) as proc:
proc.wait()
Run it:
$ python3 -m pyvirtualdisplay.examples.nested
Image:
Some programs require a functional Xauthority file. PyVirtualDisplay can
generate one and set the appropriate environment variables if you pass
use_xauth=True
to the Display
constructor. Note however that this
feature needs xauth
installed, otherwise a
pyvirtualdisplay.xauth.NotFoundError
is raised.
"Recent X servers as of version 1.13 (Xvfb, too) support the -displayfd command line option: It will make the X server choose the display itself" https://stackoverflow.com/questions/2520704/find-a-free-x11-display-number/
First help text is checked (e.g. Xvfb -help
) to find if -displayfd
flag is available.
If -displayfd
flag is available then it is used, if not then there are 10 retries by default which should be enough for starting 10 concurrent X servers.
The retries
parameter can be increased if necessary.