Difficulty accessing temporary file with web driver in Bokeh's get_screenshot_as_png function in versions above 2.3.3

Hello,

I’ve been experiencing some difficulties with Bokeh’s get_screenshot_as_png function.

It seems that in Bokeh 2.3.3, the dir parameter is not set in bokeh/io/expoty.py/ file under the class _TempFile init function, and the default TMPDIR is automatically assigned to a location visible to the web driver. In this case, the function works as expected.

However, in newer versions of Bokeh, the dir parameter is set to os.getcwd(), which the web driver cannot access.

MRE

from bokeh.plotting import figure
from bokeh.io.export import get_screenshot_as_png

import chromedriver_autoinstaller
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

p = figure()
p.circle([0], [0])


chromedriver_autoinstaller.install()
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--disable-software-rasterizer")

chrome_driver = webdriver.Chrome(options=chrome_options)

image = get_screenshot_as_png(
    p,
    driver=chrome_driver,
)
image.save(p, 'png', optimize=True)

In the code above, one can stop the code at chrome_driver = webdriver.Chrome(options=chrome_options), type chrome_driver.title and see that the property is empty.

I am working on macOS with M1 chip and have cleared permissions to the app folder. In addition, I have searched online for discussions or solutions related to this topic, but I couldn’t find any.

Has anyone else encountered this issue? If so, do you have any suggestions on how to resolve it? I would greatly appreciate any guidance or insights on this matter.

Thank you in advance for your help!

Best regards,
Ofir

@Ofir The code currently does this:

    def __init__(self, *, prefix: str = "tmp", suffix: str = "") -> None:
        # XXX: selenium has issues with /tmp directory (or equivalent), so try using the
        # current directory first, if writable, and otherwise fall back to the system
        # default tmp directory.
        try:
            self.fd, self.path = mkstemp(prefix=prefix, suffix=suffix, dir=os.getcwd())
        except OSError:
            self.fd, self.path = mkstemp(prefix=prefix, suffix=suffix)

Since we can’t really reproduce whatever it is you are seeing, your best bet is to try to figure out a better approach to take here that works for you locally, then suggest that in a GitHub Issue or Pull Request.

Ostensibly if the getcwd path does not work, it should be falling back to the system default tmpdir. Are you saying that is not happening? Please post the complete and exact error back trace you are seeing.

Hey @Bryan ,

Thank you for your reply.

The temporary file is created in the project’s root directory. However, the code fails on the wait_until_render_complete step:

def wait_until_render_complete(driver: WebDriver, timeout: int) -> None:
    '''

    '''
    from selenium.common.exceptions import TimeoutException
    from selenium.webdriver.support.wait import WebDriverWait

    def is_bokeh_loaded(driver: WebDriver) -> bool:
        return cast(bool, driver.execute_script('''
            return typeof Bokeh !== "undefined" && Bokeh.documents != null && Bokeh.documents.length != 0
        '''))

    try:
        WebDriverWait(driver, timeout, poll_frequency=0.1).until(is_bokeh_loaded)
    except TimeoutException as e:
        _log_console(driver)
        raise RuntimeError('Bokeh was not loaded in time. Something may have gone wrong.') from e

raising the RuntimeError of the above exception:

RuntimeError: Bokeh was not loaded in time. Something may have gone wrong.

Full Traceback:

File "/utility_modules/helper_functions.py", line 38, in get_plot_as_png
    get_screenshot_as_png(
File "/venv/lib/python3.10/site-packages/bokeh/io/export.py", line 239, in get_screenshot_as_png
    wait_until_render_complete(web_driver, timeout)
File "/venv/lib/python3.10/site-packages/bokeh/io/export.py", line 331, in wait_until_render_complete
    raise RuntimeError('Bokeh was not loaded in time. Something may have gone wrong.') from e
RuntimeError: Bokeh was not loaded in time. Something may have gone wrong.

@Ofir You can pass your own timeout value to export_png. Does increasing the timeout help? Are you trying to run this code on an air-gapped network or in some situation that would cause problems to load BokehJS remotely from cdn.bokeh.org?

@Bryan
Both get_screenshot_as_png and export_png were attempted using a lengthy timeout argument (>500), resulting in an identical error output.

The network I am currently operating on is not air-gapped. Another repository, running on Python 3.8 and Bokeh 2.3.3, functions seamlessly.

@Ofir I don’t have any other immediate suggestions then, I’d advise to make a GitHub Issue with full details.

I have found a solution to this Mac-related problem.

Instead of using pip install chromedriver-autoinstaller, pip install chromedriver-binary-auto should be installed.

As a result, the following code line is no longer needed chromedriver_autoinstaller.install().

That’s it! This modification should make it work.

I hope this information will come in handy and save time for other users in the future.

Cheers,
Ofir

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.