Closed Demetrio92 closed 6 years ago
So, the answer is no -- there is no such functionality in the package at the moment. Which is unfortunate, as it is easy to implement and e.g. pyLDAvis
already solved the problem.
I'll provide a custom solution below.
For cross-reference, this issue is related to #781 and #455.
Proof of concept. Tested with python 3.5 and folium 0.6.0
import numpy as np
import folium
from folium.plugins import HeatMap
# create map
data = (np.random.normal(size=(100, 3)) *
np.array([[1, 1, 1]]) +
np.array([[48, 5, 1]])).tolist()
folium_map = folium.Map([48., 5.], tiles='stamentoner', zoom_start=6)
HeatMap(data).add_to(folium_map)
# this won't work:
folium_map
folium_map.render()
# ------------------------------------------------------------------------------------------------
# so let's write a custom temporary-HTML renderer
# pretty much copy-paste of this answer: https://stackoverflow.com/a/38945907/3494126
import subprocess
import webbrowser
from http.server import BaseHTTPRequestHandler, HTTPServer
PORT = 7000
HOST = '127.0.0.1'
SERVER_ADDRESS = '{host}:{port}'.format(host=HOST, port=PORT)
FULL_SERVER_ADDRESS = 'http://' + SERVER_ADDRESS
def TemproraryHttpServer(page_content_type, raw_data):
"""
A simpe, temprorary http web server on the pure Python 3.
It has features for processing pages with a XML or HTML content.
"""
class HTTPServerRequestHandler(BaseHTTPRequestHandler):
"""
An handler of request for the server, hosting XML-pages.
"""
def do_GET(self):
"""Handle GET requests"""
# response from page
self.send_response(200)
# set up headers for pages
content_type = 'text/{0}'.format(page_content_type)
self.send_header('Content-type', content_type)
self.end_headers()
# writing data on a page
self.wfile.write(bytes(raw_data, encoding='utf'))
return
if page_content_type not in ['html', 'xml']:
raise ValueError('This server can serve only HTML or XML pages.')
page_content_type = page_content_type
# kill a process, hosted on a localhost:PORT
subprocess.call(['fuser', '-k', '{0}/tcp'.format(PORT)])
# Started creating a temprorary http server.
httpd = HTTPServer((HOST, PORT), HTTPServerRequestHandler)
# run a temprorary http server
httpd.serve_forever()
def run_html_server(html_data=None):
if html_data is None:
html_data = """
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<h1>This is a Heading</h1>
<p>This is a paragraph.</p>
</body>
</html>
"""
# open in a browser URL and see a result
webbrowser.open(FULL_SERVER_ADDRESS)
# run server
TemproraryHttpServer('html', html_data)
# ------------------------------------------------------------------------------------------------
# now let's save the visualization into the temp file and render it
from tempfile import NamedTemporaryFile
tmp = NamedTemporaryFile()
folium_map.save(tmp.name)
with open(tmp.name) as f:
folium_map_html = f.read()
run_html_server(folium_map_html)
In the above I probably should've used folium_map._repr_html_()
Also there is this SO answer that does it using IPython functionality (e.g. you can also use it vanilla python by simply installing the package)
https://stackoverflow.com/a/38797877/3494126
At some point I might tidy it up, and submit as PR.
If you fancy sending a PR please do but folium
can does have an HTML
repr
and all IDEs that can display that will work. Providing a shortcut for saving and loading a in a browser is not really a priority b/c the use case is very low.
@ocefpaf can you help me with pycharm + ipython? I am not quite sure how to make it work. I am not used to develop in a Jupiter environment, and I am sure a lot of people feel the same.
pycharm + ipython?
As far as I know IPython does not have an HTML repr, so you will have to save the HTML and load it in a browser. Just like any other python module that produces HTML and must be served to be visualized.
I don't know about pycharm
, never used it. Maybe you can ask them about it.
BTW, you can always start a local server with:
python -m http.server 8080
save the file and open it with your favorite browser.
@ocefpaf so that basically means outside of ipython notebook or jupyter you cannot really render the output without additional steps. Which is quite impractical if you have to do a lot of data manipulation before visualizing the result. It's unfair of you to say "it's on IDE to render HTML".
Yes, I am aware that python can run a web server, which is also what my solution above does. I.e. exactly this:
save the file and open it with your favorite browser.
would be nice to have it as a method to folium.folium.Map
.
For now, let's hope everyone who faces the same challenge, will stumble across this thread.
If you want to open your map in your web browser you could do something like this:
import os
import webbrowser
filepath = 'C:/whatever/map.html'
m = folium.Map()
m.save(filepath)
webbrowser.open('file://' + filepath)
On my Windows machine this opens the map in my default webbrowser. No need to run a server or anything.
Does this work for you?
@Conengmo note that some of the features, to work properly, must be served.
@Demetrio92 it is no different from a flask app and I don't think it is unfair to say that about the IDE b/c folium ultimately goal is to create a HTML map that must be served. What you ask is outside of the goa of the library.
@ocefpaf
is outside of the goa of the library
I agree, so there must be a more unified solution than 100 lines of custom code that have to be maintained by someone.
If you know if there is a two-liner to serve a webpage from a temp-file and open it in browser point me out to it.
I still think it should be a part of the package, for the same reason that map
has a save
method which could also be "not our problem" (python users should know how to save strings to files).
I any case, as far as I understood, you'd accept a PR, so it's on me now.
I still think it should be a part of the package,
I said above that it is not a priority, not that it should not be in folium
. Also, PRs welcomed :wink:
note that some of the features, to work properly, must be served.
I'm curious, what would those be? It was my understanding that everything is embedded in the single HTML file. I haven't encountered any problems so far, so it would be interesting to learn in what cases a server is needed.
^ +1 just opening an html file would definitely reduce the coding needed. It's 2 lines. One for a temp file, one for opening it.
It was my understanding that everything is embedded in the single HTML file.
I think there are still a few places where things are not embedded, my memory could be failing me though. Still, embedding was a workaround and I do want to provide a more elegant way in the long run, maybe a global embed=True/False
to create cleaner and saner HTMLs.
Embedding was a workaround? :) I did not know that. I actually like it, each file is stand-alone and portable. Makes them easy to use and share.
I actually like it, each file is stand-alone and portable. Makes them easy to use and share.
Portability was one of the goals, but the main goal was to get the repr
to display correctly on notebooks.
Having the full path to files and other resources yields a cleaner (and readable) HTML, avoid some browsers display limitations (as we can see on some notebooks with many objects and sometimes on chrome/chromium), and provide a better HTML for those who are using folium
in production to serve maps as a service.
you can save the map as html (m.save("myMap.html")) and then open with webbrowser.open("myMap.html"). It works fine with pycharm too
Too bad that #953 was never implemented.
It would have made much more sense to have a show_in_browser()
method, that would handle temporary files and removing them instead of spamming your working script directory (and possibly overwriting other HTML files) with whatever need to be temporarily created just to see the plot.
The suggestion would be:
while True: try: time.sleep(2); except KeyboardInterrupt: delete_tmp(); exit(1);
From folium 0.14.0 onwards Map
will have a show_in_browser()
method.
Hey guys i am trying to run one of the examples you provide. However, I am unable to render it. It's probably because I am using it in a normal python script inside the PyCharm. Is there any functionality similar to matplotlib
show()
? I triedrender()
but it does not do anything...