Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rendering HoloMap as GIF with matplotlib/pillow fails under Windows #3151

Closed
smillies opened this issue Nov 7, 2018 · 8 comments
Closed

Rendering HoloMap as GIF with matplotlib/pillow fails under Windows #3151

smillies opened this issue Nov 7, 2018 · 8 comments

Comments

@smillies
Copy link

@smillies smillies commented Nov 7, 2018

I am trying to create an animated gif image from a series of heat maps with HoloViews. I need to do this in a Python script, i. e. specifically not in a Jupyter notebook. I am using Python 3.7 under Windows 10.

When saving the image, Python throws a PermissionError originating from PIL\Image.py line 1966 while manipulating a temporary file. However, it doesn't seem like a user permission problem, as it happens also for users with unrestricted rights. At the point the exception happens, the temporary file has already been created on the file system.

The same code runs as expected under CentOS 7. Here's an SSCE

Here's another minimal example by ImportanceOfBeingErnest that removes holoviews from the picture by making a direct call to matplotlib's FuncAnimation.save("fname", writer="pillow", fps=5). That works OK under Windows. So it looks like the holoviews save function might be broken.

ImportanceOfBeingErnest also played around a bit in the source code of holoviews and it also fails to save via imagemagick or imagemagick_file. (Although fixing this part of the issue is probably not a priority in view of #2460)

The source of this issue is this discussion on StackOverflow.

@philippjfr
Copy link
Member

@philippjfr philippjfr commented Nov 7, 2018

Thanks @smillies, this detailed investigation is very helpful. None of the core developers use windows, which is probably why this hasn't been caught. Let's aim to get a fix for this into holoviews 1.11.0 due to be released next week.

@philippjfr philippjfr added this to the v1.11.0 milestone Nov 7, 2018
@jbednar
Copy link
Member

@jbednar jbednar commented Nov 7, 2018

I think the hv code in question is:

with NamedTemporaryFile(suffix='.%s' % fmt) as f:
                anim.save(f.name, writer=writer, **anim_kwargs)
                video = f.read()

According to the Python docs, NamedTemporaryFile has different behavior in Windows:

Whether the name can be used to open the file a second time, while the named temporary file is still open, varies across platforms (it can be so used on Unix; it cannot on Windows NT or later).

I'm not sure what anim.save is in this case, but from that description, maybe @smillies could see if the file could be closed before anim.save and opened after for the reading step? Otherwise it would seem that anim.save would need to be rewritten to take a file handle instead of a file name, and in that case it's hard to see what the point of NamedTemporaryFile is on Windows...

@smillies
Copy link
Author

@smillies smillies commented Nov 8, 2018

I don't think that the suggestion by @jbednar of closing and reopening the file is an option, because the Python docs also state that a temporary file will be destroyed as soon as it is closed.

@xavArtley
Copy link

@xavArtley xavArtley commented Nov 8, 2018

On Bokeh a small hack is performed to make NamedTemporaryFile works on windows

test_themes.py

class TestThemes(object):

def test_construct_empty_theme_from_file(self):
      # windows will throw permissions error with auto-delete
      with (tempfile.NamedTemporaryFile(delete=False)) as file:
          # create and apply empty theme with no exception thrown
          file.file.write("".encode('utf-8'))
          file.file.flush()
          theme = Theme(filename=file.name)
          theme.apply_to_model(ThemedModel())
      file.close()
      os.remove(file.name)
@smillies
Copy link
Author

@smillies smillies commented Nov 8, 2018

Thanks for the hint, @xavArtley . Importing os and doing the same in renderer.py seems to do the trick.

# Windows will throw PermissionError with auto-delete
with NamedTemporaryFile(suffix='.%s' % fmt, delete=False) as f:
    anim.save(f.name, writer=writer, **anim_kwargs)
    video = f.read()
f.close()
os.remove(f.name)

I do not feel up to testing such a change and submitting a pull request for it. Would be grateful if someone could investigate the viability of this fix.

@philippjfr
Copy link
Member

@philippjfr philippjfr commented Nov 8, 2018

Thank you both, I can confirm that this change works for me. I'll submit a PR.

@philippjfr
Copy link
Member

@philippjfr philippjfr commented Nov 8, 2018

Tentatively closing, please reopen if it doesn't work for you.

@philippjfr philippjfr closed this Nov 8, 2018
@Vikkiechauhan
Copy link

@Vikkiechauhan Vikkiechauhan commented Jul 17, 2019

hello, i want to use render the holoviews output as gif on windows. I am facing this issue as below and now i waited a long time for the output but nothing is showing up :

WARNING:root:Points05279: Setting non-parameter attribute width=500 using a mechanism intended only for parameters
WARNING:root:Points05279: Setting non-parameter attribute height=475 using a mechanism intended only for parameters
WARNING:root:Points05279: Setting non-parameter attribute size=12 using a mechanism intended only for parameters
WARNING:root:Points05279: Setting non-parameter attribute color=black using a mechanism intended only for parameters
INFO:matplotlib.animation:Animation.save using <class 'matplotlib.animation.PillowWriter'>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants