Re: [Tutor] Create Logging module
Thanks Alan, I learn alot. logger.setLevel('INFO') <- If I did not include this in the code it not generating any log I am confuse because I have setLevel to file_handler and to stream_handler file_handler.setLevel('DEBUG') stream_handler.setLevel('DEBUG') On Fri, Aug 2, 2019 at 12:14 AM Alan Gauld via Tutor wrote: > On 01/08/2019 10:11, Sinardy Xing wrote: > > > start here--- > > > > import logging > > > > ..snip... > > > > from functools import wraps > > > > def logme(func_to_log): > > import logging > > You don't need the import, it's already done in the first line. > > > > #Check log level within understanable parameter, set to INFO if is > not > > permitable value > > def check_log_level(logleveltocheck): > > This looks like an indentation error? > It should be at the same level as the import statement. > > > if any(logleveltocheck.upper() in lf for lf in ['DEBUG', > > 'INFO', 'WARNING', 'ERROR', 'CRITICAL']): > > return logleveltocheck.upper() > > Are you sure that is what you want? It seems very complicated unless you > are allowing the user to supply an abbreviated form. Otherwise > > if logleveltocheck.upper() in ['DEBUG', 'INFO', 'WARNING', >'ERROR', 'CRITICAL']: > return logleveltocheck.upper() > > might be easier? > > > else > > return 'INFO' > > > > log_file_level='INFO' #check_log_level('info') > > log_console_level='INFO' #check_log_level('info') > > > > #root level > > logger.setLevel('INFO') > > I'm not sure what this is supposed to be doing! > > > formatter = logging.Formatter('%(asctime)s :: %(name)s :: > %(levelname)s > > :: %(message)s') > > > > #Read log file from parameter > > logfile='mylogfile.log' > > file_handler = logging.FileHandler(logfile) > > file_handler.setLevel(log_file_level) > > file_handler.setFormatter(formatter) > > > > stream_handler = logging.StreamHandler() > > stream_handler.setLevel(log_console_level) > > stream_handler.setFormatter(formatter) > > > > logger.addHandler() > > logger.addHandler(stream_handler) > > > > #this wraps is to make sure we are returning func_to_log instead of > > wrapper > > @wraps(func_to_log) > > def wrapper(*args, **kwargs): > > logger.info('Ran with args: {}, and kwargs: {}'.format(args, > > kwargs)) > > return func_to_log(*args, **kwargs) > > > > return wrapper > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Create Logging module
Thank you Alan, - from previous mail > if any(logleveltocheck.upper() in lf for lf in ['DEBUG', > 'INFO', 'WARNING', 'ERROR', 'CRITICAL']): > return logleveltocheck.upper() Are you sure that is what you want? It seems very complicated unless you are allowing the user to supply an abbreviated form. Otherwise if logleveltocheck.upper() in ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']: return logleveltocheck.upper() might be easier? > else > return 'INFO' > > log_file_level='INFO' #check_log_level('info') > log_console_level='INFO' #check_log_level('info') > > #root level > logger.setLevel('INFO') I'm not sure what this is supposed to be doing! -- end I am thinking about a module where user can change the logging mode and doing so without modifying code, I am thinking to extend it with parameter module. I seen many software that if user set logging Level 1,2,3,4 or support mode, then application will create more information in the log file accordingly. The method I am using most likely is wrong. I dont know where should I trigger the log Level to achieve parameterize logging mode. I have one question I have following set stream_handler.setLevel('INFO')<--- handler to console file_handler.setLevel('INFO') < handler to file both are added to logger logger.addHandler(file_handler) logger.addHandler(stream_handler) If I did not set the logger.setLevel like following logger.setLevel('INFO') the logger unable to process logger.info('Current log level is : {}'.format(logger.level)) > return 10 if logger.setLevel('DEBUG') if not My question is what is the different between stream_handler.setLevel('INFO') and logger.setLevel('INFO') Why do we need logger.setLevel('INFO') if we stated following stream_handler.setLevel('INFO')<--- handler to console file_handler.setLevel('INFO') < handler to file --- complete code import logging #DEBUG: Detailed information, typically of interest only when diagnosing problems. #INFO : Confirmation that things are working as expected. #WARNING (default): An indication that something unexpected happened, or indicative of some problem in the near future # (e.g. 'disk space low'). The software is still working as expected. #ERROR: Due to a more serious problem, the software has not been able to perform some function. #CRITICAL :A serious error, indicating that the program itself may be unable to continue running. from functools import wraps def logme(orig_func): #Without getLogger name it will log all in root logger = logging.getLogger(__name__) #Check log level within understanable parameter, set to INFO if is not permitable value def check_log_level(logleveltocheck): #as per advised from Alan Gauld @python.org if logleveltocheck.upper() in ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']: return logleveltocheck.upper() else: return 'INFO' log_file_level='INFO' #check_log_level('info') log_console_level='INFO' #check_log_level('info') #root level logger.setLevel('DEBUG') formatter = logging.Formatter('%(asctime)s :: %(name)s :: %(levelname)s :: %(message)s') #Read log file from parameter logfile='mylogfile.log' file_handler = logging.FileHandler(logfile) file_handler.setLevel(log_file_level) file_handler.setFormatter(formatter) stream_handler = logging.StreamHandler() stream_handler.setLevel(log_console_level) stream_handler.setFormatter(formatter) logger.addHandler(file_handler) logger.addHandler(stream_handler) #this wraps is to make sure we are returning orig_func instead of wrapper @wraps(orig_func) def wrapper(*args, **kwargs): logger.info('Ran with args: {}, and kwargs: {}'.format(args, kwargs)) logger.info('Current log level is : {}'.format(logger.level)) return orig_func(*args, **kwargs) return wrapper def timer(orig_func): import time #this wraps is to make sure we are returning orig_func instead of wrapper @wraps(orig_func) def wrapper(*args, **kwargs): t1 = time.time() result = orig_func(*args, **kwargs) t2 = time.time() - t1 print('{} ran in {} sec'.format(orig_func.__name__, t2)) return result @logme def hello(name, age): print('I am {}, and I am {} years old'.format(name, age)) hello('Peter Parker', 20) On Fri, Aug 2, 2019 at 12:14 AM Alan Gauld via Tutor wrote: > On 01/08/2019 10:11, Sinardy Xing wrote: > > > start here--- > > > > import logging > > > > ..snip... > > > > from functools import wraps > > > > def logme(func_to_log): > > import logging > > You don't need the import, it's already done in the first line. > > > > #Check log level within understa
Re: [Tutor] just a quick logic check if someone has two seconds
Hi Alan, thanks for that! I realise I provided quite a lot of unnecessary info, but I've been bitten a few times with the not providing enough so thought it best. Thanks again for confirming my thoughts, that's very helpful. Nate On 02/08/2019 01:27, Alan Gauld via Tutor wrote: > On 01/08/2019 23:10, nathan tech wrote: > >> import speedtest > This is not a standard library module so I have no idea > what it does so obviously there could be magic afoot of > which I am unaware. But assuming it behaves like most > Python code... > >> def do-test(): >>test=speedtest.Speedtest() >>test.download() >>test.upload() >>return [test.download_speed, test.upload_speed] > test is garbage collected sat this point since it > goes out of scope and the returned values are passed > to the caller. Note that the returned values are not > part of the test object. The test attributes refer to > those values but it is the values themselves that > are returned. > >> Now. If I was to put this into a GUI application, I was thinking of >> having it something like this: > The fact it is a GUI is completely irrelevant. > There is nothing special about how a GUI calls a function. > >> user clicks button, >> button calls function which: >> >> 1. Shows the screen which updates with test status. >> 2, does: results=do_test() >> 3. Updates the screen with the contents of results. > The fact that the GUI calls this function is irrelevant. > A function gets called and performs some actions. > One of which is to call do_test(). It would be exactly the same if you > did this: > > for n in range(3): > result = do_test() > print(result) > > You still call the function repeatedly. > >> If the user clicks the button, say, 3 times, will I have three separate >> speedtest objects? > You will have created 3 separate speedtest instances and each > will have been garbage collected when do_test() terminated. > So you will have no speedtest instances left hanging around. > >> or will the python garbage collector clean them up for me so I only have >> one, which gets cleaned when do_test returns. > You only ever have one at a time during the execution of do_test(). > You have a total of 3 during your programs lifetime. (or however many > times you click the button!) > > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Difference between decorator and inheritance
On 7/31/19 11:57 AM, Gursimran Maken wrote: > Hi, > > Anyone could please let me know the difference between decorators and > inheritance in python. > > Both are required to add additional functionality to a method then why are > we having 2 separate things in python for doing same kind of work. I started to write something here several times and never felt like I got it right. Let me try once more without fussing too much. Python's decorators feel like a "local" thing - I have some code, and I want to make some change to it. Most often this comes up in predefined scenarios - I enable one of my functions to be line-profiled by decorating with @profile. I turn an attribute into a getter by using @property. I decorate to time a function. I decorate to add caching (memoizing) capability (@functools.lru_cache). If doesn't _have_ to be local; if I wanted to wrap a function that is not in "my" code (e.g. from Python standard library, or some module that I've obtained from the internet) I can, although the convenience form using @decorator doesn't really apply here since I don't want to modify "foreign" code; I have to use the underlying form of writing a function that generates and returns a function which augments the original function (that sounds so messy when you try to write it in English!). Inheritance is a more systematic building of relationships between classes - I can accomplish some of that with decorators, but not all. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Difference between decorator and inheritance
And now for something completely different... Decorators are not required to return a function! I use them to create a dictionary that maps function names to the corresponding function object. This is very useful when associating actions with user-entered commands. Example: def collect(func=None, d={}): if not func: return d d[func.__name__] = func @collect def add(a,b): return a+b # adds item to dictionary d (key = 'add', value = func) # repeat for other user-command functions # finally: cmd_dict = collect() # returns the dictionary cmd = input('enter a command>') func = cmd_dict.get(cmd) -- Bob Gailer ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Difference between decorator and inheritance
On 02Aug2019 11:26, bob gailer wrote: And now for something completely different... Decorators are not required to return a function! I use them to create a dictionary that maps function names to the corresponding function object. That is an interesting idea! But I want to counter it, briefly. This is very useful when associating actions with user-entered commands. Example: def collect(func=None, d={}): if not func: return d d[func.__name__] = func @collect def add(a,b): return a+b # adds item to dictionary d (key = 'add', value = func) # repeat for other user-command functions # finally: cmd_dict = collect() # returns the dictionary cmd = input('enter a command>') func = cmd_dict.get(cmd) I think you're conflating 2 things: having the decorator have a side effect outside the bare "do stuff around the call of an inner function", and returning a callable. The feature of your remark is the side effect, which is useful. Not returning a callable is orthognal, and a misfeature. Let me show you why: Python 3.7.4 (default, Jul 11 2019, 01:07:48) [Clang 8.0.0 (clang-800.0.42.1)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> d={} >>> def collect(f): d[f.__name__]=f ... >>> def g(x): print(x*2) ... >>> @collect ... def h(x): print(x*3) ... >>> g(8) 16 >>> h(8) Traceback (most recent call last): File "", line 1, in TypeError: 'NoneType' object is not callable The return value of the decorator is bound to the function name in the current scope,typically the current module for a normal function or the enclosing class for a method. Your decorator returns None (I'm ignoring the d={} funkiness for now). Therefore a side effect of using the decorator is that every function "foo" you use with this decorator defines the name "foo" in the current scope as None. As you can see in the example above, that makes the h() function not usable on its own. (And litters the namespace with a useless "h" name whose value is None.) Had my version of your decorator looked like this: def collect(f): d[f.__name__] = f return f then h() would have remained independently useful, at no cost to the functionality of your decorator. So I'm arguing that while you _can_ return None from a decorator (which is what is actually happening in your "not returning" phrasing), it remains _useful_ and _easy_ to return the decorated function itself unchanged. I've concerns about your d={} trick too, but we can discuss those in another subthread if you like. I'm hoping to convince you that your otherwise nifty @collect decorator could do with returning the function unchanged after doing its work. Finally, there is another important reason to return the function (or another callable): nesting decorators. Look at this piece of code from a project I'm working on: @classmethod @auto_session @require(lambda console: isinstance(console, Console)) @require(lambda top_node: isinstance(top_node, DirTreeNode)) @require(lambda top_node: not hasattr(top_node, 'can_uuid')) def from_fstree(cls, console, top_node, *, session): This is a method, but otherwise the situation is no different. Each of these decorators does a little task and returns a callable, ready for further decoration by outer decorators. So every one of them returns a suitable callable. If your @collect decorator returned the function, it too could be happily placed in such a nesting of decorators and everyone is happy. Because it does not, it does not play well with others, because an outer decorator would not have a callable to work with; it would get the None that your @collect returns. This is the other argument for always returning a callable: to interoperate with other decorators, or of course anything else which works with a callable. Cheers, Cameron Simpson ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Name for this type of class?
They same naming is one of the two biggest challenges when it comes to software. Or one of three if you count the "off-by-one" joke :) Anyways, I'm looking for help coming up for the proper name for a class that collects the following type of telemetry data that we use for operational analysis. We use various combinations of these attributes depending on context. event_type event_step file_count line_count byte_count row_count batch_count job_count error_count warning_count duration Here are the ways we've come up with to describe a class that collects this info: JobMetrics JobStats or JobStatistics JobTelemetry None of these feel right and of course everyone on our team has a different opinion. Does this question ring any bells? Thank you, Malcolm ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Name for this type of class?
On 02Aug2019 17:47, Malcolm Greene wrote: They same naming is one of the two biggest challenges when it comes to software. Or one of three if you count the "off-by-one" joke :) Anyways, I'm looking for help coming up for the proper name for a class that collects the following type of telemetry data that we use for operational analysis. We use various combinations of these attributes depending on context. event_type event_step file_count line_count byte_count row_count batch_count job_count error_count warning_count duration Here are the ways we've come up with to describe a class that collects this info: JobMetrics JobStats or JobStatistics JobTelemetry None of these feel right and of course everyone on our team has a different opinion. Well they could all subclass types.SimpleNamespace, and I personally think JobTelemetry or Telemetry sound fine given your description. Unless they're snapshots/samples, in which case "Telemetric" ?-) Cheers, Cameron Simpson ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Name for this type of class?
On 03/08/2019 00:47, Malcolm Greene wrote: > Anyways, I'm looking for help coming up for the proper name for a class that > collects the following type of telemetry data Classes should never be named for their data but for their function. What does this class do? What operations does it support. Does the internal data support those operations? Or is it really several classes conflated into one for "convenience"? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Name for this type of class?
On 2019-08-02 16:47, Malcolm Greene wrote: They same naming is one of the two biggest challenges when it comes to software. Or one of three if you count the "off-by-one" joke :) Anyways, I'm looking for help coming up for the proper name for a class that collects the following type of telemetry data that we use for operational analysis. We use various combinations of these attributes depending on context. event_type event_step file_count line_count byte_count row_count batch_count job_count error_count warning_count duration Here are the ways we've come up with to describe a class that collects this info: JobMetrics JobStats or JobStatistics JobTelemetry What about TelData for the class and job_data for an instance of the class? You might prefer TelemetryStatistics. It seems to me that the word 'job' would be more appropriate as (or part of) an instance name rather than the class name. Sounds like a question for "an English Major". (Any Garrison Keillor fans out there?) ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor