Re: [Tutor] Create Logging module

2019-08-02 Thread Sinardy Xing
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

2019-08-02 Thread Sinardy Xing
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

2019-08-02 Thread nathan tech
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

2019-08-02 Thread Mats Wichmann
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

2019-08-02 Thread bob gailer

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

2019-08-02 Thread Cameron Simpson

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?

2019-08-02 Thread Malcolm Greene
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?

2019-08-02 Thread Cameron Simpson

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?

2019-08-02 Thread Alan Gauld via Tutor
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?

2019-08-02 Thread Alex Kleider

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