问题
Asking this again as the previous has been closed without any useful solution.
I am trying to produce few charts in a loop and save them automatically.
I am working on Windows, using Chrome.
I have been following the documentation on how to save a chart in svg.
I downloaded the appropriate ChromeDriver for my Chrome version.
gdf
is my geodataframe and everything works smoothly and I can generate and manually save charts.
Also, this example taken from the chromium documentation works:
import time
from selenium import webdriver
driver = webdriver.Chrome('pathtochromedriver/chromedriver_win32/chromedriver.exe')
driver.get('http://www.google.com/');
time.sleep(5) # Let the user actually see something!
search_box = driver.find_element_by_name('q')
search_box.send_keys('ChromeDriver')
search_box.submit()
time.sleep(5) # Let the user actually see something!
driver.quit()
Below is the piece of code I am trying to run:
#Chromedriver for headless run and chart automatic save
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument("--headless")
####### None of the following work!
#driver = webdriver.Chrome(chrome_options=chrome_options, executable_path=r'pathtochromedriver/chromedriver_win32/chromedriver.exe')
#driver = webdriver.Chrome(executable_path=r'pathtochromedriver/chromedriver_win32/chromedriver.exe')
driver = webdriver.Chrome('pathtochromedriver/chromedriver_win32/chromedriver.exe')
#
#loop
for group in gdf['Group Name'].unique():
map_1km_json = json.loads(gdf[gdf['Group Name']==group].to_json())
map_1km_data = alt.Data(values=map_1km_json['features'])
data_1km_geojson = alt.InlineData(values=map_1km, format=alt.DataFormat(property='features',type='json'))
domain=[1,2]
range_=['#b0d247','#007bd1']
choro1_5 = alt.Chart(map_1km_data).mark_geoshape().encode(
alt.Color('properties.Cat2:O', scale=alt.Scale(domain=domain, range=range_),title = "Havvandsstigning"),
#alt.Color('properties.Cat2', type='quantitative', scale=alt.Scale(scheme='plasma'),title = "Havvandsstigning")
tooltip = ['properties.dd_km1:N','properties.Cat2:N']
).properties(
width=1100,
height=800
)
(background + choro1_5).save("{}.svg".format(bank))
driver.quit()
Running the code opens an empty new chrome pane (in the background) that looks like this, which hints to the fact that the chromedriver is working smoothly:
But the code returns the following error:
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
~\Anaconda3\lib\site-packages\selenium\webdriver\common\service.py in start(self)
75 stderr=self.log_file,
---> 76 stdin=PIPE)
77 except TypeError:
~\Anaconda3\lib\subprocess.py in __init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, encoding, errors, text)
774 errread, errwrite,
--> 775 restore_signals, start_new_session)
776 except:
~\Anaconda3\lib\subprocess.py in _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, unused_restore_signals, unused_start_new_session)
1177 os.fspath(cwd) if cwd is not None else None,
-> 1178 startupinfo)
1179 finally:
FileNotFoundError: [WinError 2] The system cannot find the file specified
During handling of the above exception, another exception occurred:
WebDriverException Traceback (most recent call last)
<ipython-input-27-6067387e4b2f> in <module>
19 height=800
20 )
---> 21 (background + choro1_5).save("{}.svg".format(bank))
22 driver.quit()
~\Anaconda3\lib\site-packages\altair\vegalite\v3\api.py in save(self, fp, format, override_data_transformer, scale_factor, vegalite_version, vega_version, vegaembed_version, **kwargs)
478 if override_data_transformer:
479 with data_transformers.disable_max_rows():
--> 480 result = save(**kwds)
481 else:
482 result = save(**kwds)
~\Anaconda3\lib\site-packages\altair\utils\save.py in save(chart, fp, vega_version, vegaembed_version, format, mode, vegalite_version, embed_options, json_kwds, webdriver, scale_factor, **kwargs)
102 vegaembed_version=vegaembed_version,
103 webdriver=webdriver,
--> 104 scale_factor=scale_factor, **kwargs)
105 if format == 'png':
106 write_file_or_filename(fp, mimebundle['image/png'], mode='wb')
~\Anaconda3\lib\site-packages\altair\utils\mimebundle.py in spec_to_mimebundle(spec, format, mode, vega_version, vegaembed_version, vegalite_version, **kwargs)
54 vega_version=vega_version,
55 vegaembed_version=vegaembed_version,
---> 56 vegalite_version=vegalite_version, **kwargs)
57 if format == 'png':
58 render = base64.b64decode(render.split(',', 1)[1].encode())
~\Anaconda3\lib\site-packages\altair\utils\headless.py in compile_spec(spec, format, mode, vega_version, vegaembed_version, vegalite_version, scale_factor, driver_timeout, webdriver)
152 webdriver_options.add_argument('--no-sandbox')
153
--> 154 driver = webdriver_class(options=webdriver_options)
155
156 try:
~\Anaconda3\lib\site-packages\selenium\webdriver\chrome\webdriver.py in __init__(self, executable_path, port, options, service_args, desired_capabilities, service_log_path, chrome_options, keep_alive)
71 service_args=service_args,
72 log_path=service_log_path)
---> 73 self.service.start()
74
75 try:
~\Anaconda3\lib\site-packages\selenium\webdriver\common\service.py in start(self)
81 raise WebDriverException(
82 "'%s' executable needs to be in PATH. %s" % (
---> 83 os.path.basename(self.path), self.start_error_message)
84 )
85 elif err.errno == errno.EACCES:
WebDriverException: Message: 'chromedriver' executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home
回答1:
The reason your code does not work is because you are not passing your driver instance to Altair, and so Altair is creating a default driver instance and looking for chromedriver in the default location.
Altair currently does not support passing a custom driver instance to the save()
method, so saving a figure in the way you are attempting above is not possible, unless chromedriver can be made available at the default location.
We are in the process of improving this, however, with the altair_saver package. With it, you can pass a custom driver instance to the save method:
from altair_saver import save
# ...
chart = background + choro1_5
filename = f"{bank}.svg"
save(chart, filename, method='selenium', webdriver=driver)
In a future Altair release, this more flexible saver extension will replace Altair's current built-in chart.save()
method.
回答2:
Have a look at Altair Saver project. It uses Chrome Driver and Selenium. Install via pip or conda. It can save to svg:
from altair_saver import save
save((background + choro1_5), "{}.svg".format(bank))
来源:https://stackoverflow.com/questions/59897022/altair-automatic-save-chart-using-selenium-chromedriver