Open StuartGordonReid opened 7 years ago
I worked on this a bit for #170 and didn't make it very far. Help here is greatly appreciated :-) We may need an upstream change.
Here's a decorator that DOES suppress output:
# from https://stackoverflow.com/questions/11130156/suppress-stdout-stderr-print-from-python-functions
class suppress_stdout_stderr(object):
'''
A context manager for doing a "deep suppression" of stdout and stderr in
Python, i.e. will suppress all print, even if the print originates in a
compiled C/Fortran sub-function.
This will not suppress raised exceptions, since exceptions are printed
to stderr just before a script exits, and after the context manager has
exited (at least, I think that is why it lets exceptions through).
'''
def __init__(self):
# Open a pair of null files
self.null_fds = [os.open(os.devnull, os.O_RDWR) for x in range(2)]
# Save the actual stdout (1) and stderr (2) file descriptors.
self.save_fds = (os.dup(1), os.dup(2))
def __enter__(self):
# Assign the null pointers to stdout and stderr.
os.dup2(self.null_fds[0], 1)
os.dup2(self.null_fds[1], 2)
def __exit__(self, *_):
# Re-assign the real stdout/stderr back to (1) and (2)
os.dup2(self.save_fds[0], 1)
os.dup2(self.save_fds[1], 2)
# Close the null files
os.close(self.null_fds[0])
os.close(self.null_fds[1])
# used like
with suppress_stdout_stderr():
p = Propet(*kwargs).fit(training_data)
@randlet Awesome. Has this been pulled?
Not yet, but I would be happy to work up a PR this week if @bletham is ok with using a context manager to (optionally) suppress output.
Actually, I don't know how the copyright/FB contributors agreement would work for this. I didn't write the code and AFAIK Stack Overflow snippets (prior to 2016) are licensed with CC Share Alike license. @bletham do you know if it's possible for you to accept PR's for code that has a CC-SA license?
@randlet thanks for posting this, this is really great and should be immediately useful to people.
I'm not sure about the license thing. I think I'm inclined to just leave this issue open so that people can find and use the decorator, and then wait a bit longer on the Stan team for an upstream fix. They're definitely aware of the issue (https://github.com/stan-dev/rstan/issues/49) and say as of April that it will be suppressed soon, then it'll just be a matter of adding the verbose arg to prophet.
That approach makes good sense to me. Thanks!
Just wanted to post an update to this. We are running Prophet in a long running process doing lots of forecasting and found we were running out of file descriptors pretty quickly causing issues on the server. I finally traced it back to the decorator posted above which leaks 2 file descriptors every time it is used.
I have modified it to the following with success:
class suppress_stdout_stderr(object):
'''
A context manager for doing a "deep suppression" of stdout and stderr in
Python, i.e. will suppress all print, even if the print originates in a
compiled C/Fortran sub-function.
This will not suppress raised exceptions, since exceptions are printed
to stderr just before a script exits, and after the context manager has
exited (at least, I think that is why it lets exceptions through).
'''
def __init__(self):
# Open a pair of null files
self.null_fds = [os.open(os.devnull, os.O_RDWR) for x in range(2)]
# Save the actual stdout (1) and stderr (2) file descriptors.
self.save_fds = [os.dup(1), os.dup(2)]
def __enter__(self):
# Assign the null pointers to stdout and stderr.
os.dup2(self.null_fds[0], 1)
os.dup2(self.null_fds[1], 2)
def __exit__(self, *_):
# Re-assign the real stdout/stderr back to (1) and (2)
os.dup2(self.save_fds[0], 1)
os.dup2(self.save_fds[1], 2)
# Close the null files
for fd in self.null_fds + self.save_fds:
os.close(fd)
Hi. I've got here from issue #219, yet this solution definitely does not work with Prophet.fit logger.INFO messages like "Disabling yearly seasonality..." and "Disabling daily seasonality...". I'm quite at a loss of how to get rid of them, actually. Nothing works.
Nevermind. Turns out that if you specify "daily_seasonality=False" etc. the messages disappear. Although why on earth an unspecified parameter should generate a console output, Facebook knows.
Those messages can be disabled by setting the logging level for fbprophet to something above INFO:
import logging
logging.getLogger('fbprophet').setLevel(logging.WARNING)
The reason for them is to avoid a scenario where a new user fits a time series with default values, seasonality is disabled e.g. due to too short a time series, but the user doesn't know this and is left wondering why the seasonality doesn't show up in the plot like in the documentation. With the info message they will know that it was on purpose and not a bug.
Hello Ben, Thank you for your answer. Sorry about the earlier disgruntled post and about the delay in my response. I've tried logging before, probably with the wrong syntax. However, now it works. Thanks.
Any progress on this? I just started to experiment with Prophet in an existing application which spits out HTML to stdout. All this business about log joing probabilities and Hessians is wreaking havoc with that. I finally had to wrap this sort of business around my prophet calls:
stdout = os.dup(1)
stderr = os.dup(2)
null = os.open(os.devnull, os.O_RDWR)
os.dup2(null, 1)
os.dup2(null, 2)
try:
... prophet calls here ...
finally:
os.dup2(stdout, 1)
os.dup2(stderr, 2)
I will eventually turn that into a decorator. Still would be nice to have an official way to do that suppression, one which didn't require so many system calls... (I'm guessing Stan has no clean way to tell it to shut up?)
I'm using 0.2.1 (package from Conda forge). Maybe a later version has this problem solved?
The upstream issue in Stan is still open, there is nothing in the later version of prophet to fix this. I was hoping for an upstream fix to avoid having to mess around with redirecting stderr, but we may have to just do it for the next version. In the meantime a decorator like that is the way to go.
Is there a link to the docs on how to do this? I'm running thousands of simulations and this is killing me...
Hi drcrook1,
I'm not sure what did the job for me, but it was either logging or suppress_stdout_stderr above. I had a class which had: a. suppress_stdout_stderr as a sub class b. a fit function that called for suppress_stdout_stderr: The relevant parts of the code are:
import logging
from fbprophet import Prophet
logging.getLogger('fbprophet').setLevel(logging.WARNING)
model = Prophet()
with self.suppress_stdout_stderr():
model.fit(fit_data)
Hopes it helps.
Errr.. There was a question by shaidams64 which I don't see now, but I would answer anyway: suppress_stdout_stderr wasn't a sub class of a fit class. I had a parent class which managed the entire simulation which had suppress_stdout_stderr as a sub_class and also had a fit function that used that class in the way I've quoted above. The model.fit class which was used on the fit function was imported from another library. The fit function and suppress_stdout_stderr class are both children of the same parent class.
I found that :
1 . suppress_stdout_stderr
works if you run it in main process .
@eromoe hi, it fixes using this. This will help you silence logger
import logging from fbprophet import Prophet logging.getLogger('fbprophet').setLevel(logging.WARNING) model = Prophet() with self.suppress_stdout_stderr(): model.fit(fit_data)
@eromoe, I have this successfully blocking the output across multiple processes.
Using the wrapper code, I was able to suppress INFO logs but is there a way to stop WARNING logs too?
I tried setting the log level to ERROR but still WARNING logs appear.
logging.getLogger('fbprophet').setLevel(logging.ERROR)
@ShreyasJothish this should do it.
# Turn off pystan warnings
warnings.simplefilter("ignore", DeprecationWarning)
warnings.simplefilter("ignore", FutureWarning)
# Turn off fbprophet stdout logger
logging.getLogger('fbprophet').setLevel(logging.ERROR)
I have tried the solution from @bletham and the one from @sammo but nothing, still having those Iteration messages.
@RonanFelipe Use the suppression class given above from @randlet https://github.com/facebook/prophet/issues/223#issuecomment-326455744
Then use:
import logging
from fbprophet import Prophet
logging.getLogger('fbprophet').setLevel(logging.WARNING)
model = Prophet()
with self.suppress_stdout_stderr():
model.fit(fit_data)
Thanks @mattc-eostar, it worked.
Running the code proposed by @randlet solved it for me thank you so much.
However running this on AWS lambda sometimes gives me this error multiple times:
OSError: [Errno 24] Too many open files: '/dev/null'
Can anyone help? python3.7 pystan==2.18 fbprophet==0.5
@CrashLaker did you see my revised code which addresses running out of file descriptors here: https://github.com/facebook/prophet/issues/223#issuecomment-326455744
Is there a workaround to suppress stan output in R?
@ShreyasJothish this should do it.
# Turn off pystan warnings warnings.simplefilter("ignore", DeprecationWarning) warnings.simplefilter("ignore", FutureWarning) # Turn off fbprophet stdout logger logging.getLogger('fbprophet').setLevel(logging.ERROR)
thanks it worked
It didn't work for me while I am using the cross_validation while model fitting using dask, Does anyone know a workaround for that thing?
I was using this like this.
with self.suppress_stdout_stderr(): df_cv = cross_validation(m, horizon='7 days', period='7 days', initial='500 days', parallel='dask')
Any progress on getting a module level option?
import logging from fbprophet import Prophet logging.getLogger('fbprophet').setLevel(logging.WARNING) model = Prophet() with self.suppress_stdout_stderr(): model.fit(fit_data)
@eromoe, I have this successfully blocking the output across multiple processes.
just wanted to point out that Facebook has since changed the naming of the module, so the above code isn't working properly anymore, i have taken liberty to modify it to my own use (I'm calling prophet inside a function on multiple cores using multiprocessing module), below is my code:
import warnings
import logging
import os
from prophet import Prophet
def func():
warnings.simplefilter("ignore", DeprecationWarning)
warnings.simplefilter("ignore", FutureWarning)
logging.getLogger('prophet').setLevel(logging.ERROR) #Notice that i had modified the name from 'fbprophet' to just 'prophet'
.......
model = Prophet()
with suppress_stdout_stderr():
model.fit(fit_data)
i hope it helps anyone who wonders here for the same issue.
import logging from fbprophet import Prophet logging.getLogger('fbprophet').setLevel(logging.WARNING) model = Prophet() with self.suppress_stdout_stderr(): model.fit(fit_data)
@eromoe, I have this successfully blocking the output across multiple processes.
just wanted to point out that Facebook has since changed the naming of the module, so the above code isn't working properly anymore, i have taken liberty to modify it to my own use (I'm calling prophet inside a function on multiple cores using multiprocessing module), below is my code:
import warnings import logging import os from prophet import Prophet def func(): warnings.simplefilter("ignore", DeprecationWarning) warnings.simplefilter("ignore", FutureWarning) logging.getLogger('prophet').setLevel(logging.ERROR) #Notice that i had modified the name from 'fbprophet' to just 'prophet' ....... model = Prophet() with suppress_stdout_stderr(): model.fit(fit_data)
i hope it helps anyone who wonders here for the same issue. Didn't work for me, unfortunately. I'm using prophet on IBM Cloud.
FYI, the previous class suppress_stdout_stderr
will not work appropriately in multi-thread tasks
with
block might be suppressedwith
block might still be printed outHi, I have class suppress_stdout_stderr and worked for me, but I would like to stop it. anyone can help with this
`class suppress_stdout_stderr(object): def init(self):
self.null_fds = [os.open(os.devnull, os.O_RDWR) for x in range(2)]
# Save the actual stdout (1) and stderr (2) file descriptors.
self.save_fds = (os.dup(1), os.dup(2))
def __enter__(self):
# Assign the null pointers to stdout and stderr.
os.dup2(self.null_fds[0], 1)
os.dup2(self.null_fds[1], 2)
def __exit__(self, *_):
# Re-assign the real stdout/stderr back to (1) and (2)
os.dup2(self.save_fds[0], 1)
os.dup2(self.save_fds[1], 2)
# Close the null files
os.close(self.null_fds[0])
os.close(self.null_fds[1])`
class suppress_stdout_stderr(object): ''' A context manager for doing a "deep suppression" of stdout and stderr in Python, i.e. will suppress all print, even if the print originates in a compiled C/Fortran sub-function. This will not suppress raised exceptions, since exceptions are printed to stderr just before a script exits, and after the context manager has exited (at least, I think that is why it lets exceptions through). ''' def __init__(self): # Open a pair of null files self.null_fds = [os.open(os.devnull, os.O_RDWR) for x in range(2)] # Save the actual stdout (1) and stderr (2) file descriptors. self.save_fds = [os.dup(1), os.dup(2)] def __enter__(self): # Assign the null pointers to stdout and stderr. os.dup2(self.null_fds[0], 1) os.dup2(self.null_fds[1], 2) def __exit__(self, *_): # Re-assign the real stdout/stderr back to (1) and (2) os.dup2(self.save_fds[0], 1) os.dup2(self.save_fds[1], 2) # Close the null files for fd in self.null_fds + self.save_fds: os.close(fd)
I don't think you need to open /dev/null
twice. And for this kind of simple context manager use, you don't necessarily need an __init__
separate from __enter__
. Here is a modified version:
from types import TracebackType
from typing import Union
class SilentStdoutStderr(object):
"""
Context manager to temporarily silence stdout and stderr. Use with `with`.
"""
stdout, stderr = sys.__stdout__.fileno(), sys.__stderr__.fileno()
def __enter__(self) -> None:
self.devnull = os.open(os.devnull, os.O_RDWR)
self.orig_stdout, self.orig_stderr = os.dup(self.stdout), os.dup(self.stderr)
# point stdout, stderr to /dev/null
os.dup2(self.devnull, self.stdout)
os.dup2(self.devnull, self.stderr)
def __exit__(
self,
exc_type: Union[type[BaseException], None],
exc_val: Union[BaseException, None],
exc_tb: Union[TracebackType, None],
) -> None:
print(flush=True)
# restore stdout, stderr back
os.dup2(self.orig_stdout, self.stdout)
os.dup2(self.orig_stderr, self.stderr)
# close all file descriptors
for file in [self.devnull, self.orig_stdout, self.orig_stderr]:
os.close(file)
But this is not important, both work anyway.
However, I managed to silence logging with just:
import logging
logging.getLogger("prophet").setLevel(logging.WARNING)
logging.getLogger("cmdstanpy").disabled=True
I want to revert it back to see log, how can I do that?
Thank you @samposm what you quoted worked for me as well:
import logging
logging.getLogger("prophet").setLevel(logging.WARNING)
logging.getLogger("cmdstanpy").disabled=True
class suppress_stdout_stderr(object): ''' A context manager for doing a "deep suppression" of stdout and stderr in Python, i.e. will suppress all print, even if the print originates in a compiled C/Fortran sub-function. This will not suppress raised exceptions, since exceptions are printed to stderr just before a script exits, and after the context manager has exited (at least, I think that is why it lets exceptions through). ''' def __init__(self): # Open a pair of null files self.null_fds = [os.open(os.devnull, os.O_RDWR) for x in range(2)] # Save the actual stdout (1) and stderr (2) file descriptors. self.save_fds = [os.dup(1), os.dup(2)] def __enter__(self): # Assign the null pointers to stdout and stderr. os.dup2(self.null_fds[0], 1) os.dup2(self.null_fds[1], 2) def __exit__(self, *_): # Re-assign the real stdout/stderr back to (1) and (2) os.dup2(self.save_fds[0], 1) os.dup2(self.save_fds[1], 2) # Close the null files for fd in self.null_fds + self.save_fds: os.close(fd)
I don't think you need to open
/dev/null
twice. And for this kind of simple context manager use, you don't necessarily need an__init__
separate from__enter__
. Here is a modified version:from types import TracebackType from typing import Union class SilentStdoutStderr(object): """ Context manager to temporarily silence stdout and stderr. Use with `with`. """ stdout, stderr = sys.__stdout__.fileno(), sys.__stderr__.fileno() def __enter__(self) -> None: self.devnull = os.open(os.devnull, os.O_RDWR) self.orig_stdout, self.orig_stderr = os.dup(self.stdout), os.dup(self.stderr) # point stdout, stderr to /dev/null os.dup2(self.devnull, self.stdout) os.dup2(self.devnull, self.stderr) def __exit__( self, exc_type: Union[type[BaseException], None], exc_val: Union[BaseException, None], exc_tb: Union[TracebackType, None], ) -> None: print(flush=True) # restore stdout, stderr back os.dup2(self.orig_stdout, self.stdout) os.dup2(self.orig_stderr, self.stderr) # close all file descriptors for file in [self.devnull, self.orig_stdout, self.orig_stderr]: os.close(file)
But this is not important, both work anyway.
However, I managed to silence logging with just:
import logging logging.getLogger("prophet").setLevel(logging.WARNING) logging.getLogger("cmdstanpy").disabled=True
Thanks sir, saved a lot of time and headache looking at the cmdstanpy logs
Hi,
I recently started using Prophet in Python, and whilst it is working (quite well), it is printing out messages which appear to be generated by PySTAN and suppressing output from stdout, stderr, and stdin doesn't seem to stop it. Could you add an option to suppress output from PySTAN. I've attached screenshots of the output and the function I am trying to use to suppress the output which is not working:
Kind regards, Stuart Reid