Firefox started by Selenium ignores the display created by pyvirtualdisplay
firefox, python, pyvirtualdisplay, selenium
Solution
Solution
Move your creation of the `FirefoxBinary` object inside the context managed by `pyvirtualdisplay.Display`:
from selenium import webdriver
from selenium.webdriver.firefox.webdriver import FirefoxBinary
import pyvirtualdisplay
with pyvirtualdisplay.Display(visible=True):
if True: # Set to False to use Chrome...
binary = FirefoxBinary()
driver = webdriver.Firefox(None, binary)
else:
driver = webdriver.Chrome()
driver.get("http://www.google.com")
driver.quit()
Explanation
The problem is what happens behind the scenes. The environment variable named `DISPLAY` is what determines where Firefox and Chrome will connect to. It is not set in the way you'd expect it to be set.
Here is what happens with your code:
You create an instance of `FirefoxBinary`. If you read the source code, you'll see that when an object of this class is created it makes a copy of `os.environ` (the environment).
You create a display with `pyvirtualdisplay.Display` and use it as a context manager. As you enter the context, the display alters `os.environ` so that as long as the context is in effect, the `DISPLAY` environment variable is set so that X clients will connect to the new display instead of what `DISPLAY` was before the context came into effect.
You create your driver. When you use Chrome, everything is fine because Chrome will get its `DISPLAY` variable from the modified environment. However, when you use Firefox, it will use the `DISPLAY` environment from the environment that was copied in the first step. This environment contains a value of `DISPLAY` which is prior to the alteration described in the previous step, so it does not connect to the new display you created.
Problem
I start a display with `pyvirtualdisplay` before creating my `WebDriver` instance. If I use Chrome, it works without any problem: Chrome shows up in the Xephyr instance that `pyvirtualdisplay` creates. However, when I use Firefox, the Xephyr instance appears but Firefox shows up outside of it. Here is code that fully reproduces the problem: ``` from selenium import webdriver from selenium.webdriver.firefox.webdriver import FirefoxBinary import pyvirtualdisplay binary = FirefoxBinary() with pyvirtualdisplay.Display(visible=True): if True: # Set to False to use Chrome... driver = webdriver.Firefox(None, binary) else: driver = webdriver.Chrome() driver.get("http://www.google.com") driver.quit() ``` The code above is a minimal version of code that is more complex (which explains the seemingly useless `FirefoxBinary()`).