Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #106439

Re: how to optimize the below code with a helper function

Path csiph.com!feeder.erje.net!2.eu.feeder.erje.net!ecngs!testfeeder.ecngs.de!81.171.118.64.MISMATCH!peer04.fr7!news.highwinds-media.com!fu-berlin.de!uni-berlin.de!not-for-mail
From "Martin A. Brown" <martin@linux-ip.net>
Newsgroups comp.lang.python
Subject Re: how to optimize the below code with a helper function
Date Mon, 4 Apr 2016 07:07:20 -0700
Lines 160
Message-ID <mailman.17.1459779248.32530.python-list@python.org> (permalink)
References <CACT3xuUQc9wFPqG1DHM0ecwKE2J8KiFKFDui=FvWBqccAGLEoA@mail.gmail.com> <alpine.LSU.2.11.1604040639570.18407@znpeba.jbaqresebt.arg>
Mime-Version 1.0
Content-Type text/plain; charset=US-ASCII
X-Trace news.uni-berlin.de NyDNlZhyWvuKbydmUPrbQgIAIn5p1UIjAJYgV9hI+zoQ==
Return-Path <martin@linux-ip.net>
X-Original-To python-list@python.org
Delivered-To python-list@mail.python.org
X-Spam-Status OK 0.000
X-Spam-Evidence '*H*': 1.00; '*S*': 0.00; 'args': 0.04; 'sys': 0.05; '__name__': 0.07; 'main()': 0.07; 'skip:/ 10': 0.07; 'subject:code': 0.07; 'cc:addr:python-list': 0.09; '__future__': 0.09; 'although,': 0.09; 'func': 0.09; 'logger': 0.09; 'observation': 0.09; 'testcases': 0.09; 'variables,': 0.09; 'python': 0.10; 'def': 0.13; "'__main__':": 0.16; 'arguments:': 0.16; 'd.items():': 0.16; 'dictionary,': 0.16; 'division,': 0.16; 'from:addr:martin': 0.16; 'function?': 0.16; 'guessing': 0.16; 'i.e': 0.16; 'idea:': 0.16; 'jumps': 0.16; 'luck,': 0.16; 'main():': 0.16; 'received:hsd1.or.comcast.net': 0.16; 'received:io': 0.16; 'received:or.comcast.net': 0.16; 'received:psf.io': 0.16; 'yank': 0.16; 'string': 0.17; 'helper': 0.18; 'skip:l 30': 0.18; 'test.': 0.18; 'variable': 0.18; 'all,': 0.20; 'cc:2**0': 0.20; 'cc:addr:python.org': 0.20; 'martin': 0.22; 'function,': 0.22; 'rid': 0.22; 'simpler': 0.22; 'code,': 0.23; '(or': 0.23; 'seems': 0.23; '(you': 0.23; 'this:': 0.23; 'import': 0.24; 'header:In-Reply-To:1': 0.24; 'sort': 0.25; 'testing': 0.25; 'command': 0.26; 'sense': 0.26; 'external': 0.27; 'figure': 0.27; 'error': 0.27; 'logging': 0.27; 'parameters': 0.27; 'question': 0.27; 'data,': 0.27; 'sequence': 0.27; 'received:24': 0.28; 'function': 0.28; "skip:' 10": 0.28; 'looks': 0.29; 'command- line': 0.29; 'dictionary': 0.29; "i'm": 0.30; 'code': 0.30; 'becomes': 0.30; 'call.': 0.30; 'putting': 0.30; 'guess': 0.31; 'operations': 0.31; 'probably': 0.31; 'operate': 0.32; 'though,': 0.32; 'url:python': 0.33; 'call,': 0.33; 'optimize': 0.33; 'received:comcast.net': 0.33; 'similar': 0.33; 'case,': 0.34; 'file': 0.34; 'handle': 0.34; 'skip:d 20': 0.34; 'gets': 0.35; 'could': 0.35; 'something': 0.35; 'expected': 0.35; 'but': 0.36; 'should': 0.36; 'there': 0.36; 'url:org': 0.36; 'basic': 0.36; 'cases': 0.36; 'data.': 0.36; 'keyword': 0.36; 'subject:: ': 0.37; 'done.': 0.37; 'charset:us-ascii': 0.37; 'mean': 0.38; 'skip:o 20': 0.38; 'end': 0.39; 'why': 0.39; 'test': 0.39; 'data': 0.39; 'subject:the': 0.39; 'easily': 0.39; 'well.': 0.40; 'where': 0.40; 'subject:with': 0.40; 'your': 0.60; 'received:network': 0.61; 'further': 0.62; 'more': 0.63; 'different': 0.63; 'sample': 0.63; 'times': 0.63; 'here': 0.66; 'wish': 0.71; 'greetings': 0.71; '100': 0.79; '**kw)': 0.84; '**kw):': 0.84; '>function': 0.84; 'avoid.': 0.84; 'dict()': 0.84; 'scenarios,': 0.84; 'subject:below': 0.84; 'url:tutorial': 0.91
X-X-Sender mabrown@macron.wonderfrog.net
In-Reply-To <CACT3xuUQc9wFPqG1DHM0ecwKE2J8KiFKFDui=FvWBqccAGLEoA@mail.gmail.com>
X-BeenThere python-list@python.org
X-Mailman-Version 2.1.21
Precedence list
List-Id General discussion list for the Python programming language <python-list.python.org>
List-Unsubscribe <https://mail.python.org/mailman/options/python-list>, <mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive <http://mail.python.org/pipermail/python-list/>
List-Post <mailto:python-list@python.org>
List-Help <mailto:python-list-request@python.org?subject=help>
List-Subscribe <https://mail.python.org/mailman/listinfo/python-list>, <mailto:python-list-request@python.org?subject=subscribe>
X-Mailman-Original-Message-ID <alpine.LSU.2.11.1604040639570.18407@znpeba.jbaqresebt.arg>
X-Mailman-Original-References <CACT3xuUQc9wFPqG1DHM0ecwKE2J8KiFKFDui=FvWBqccAGLEoA@mail.gmail.com>
X-Received-Bytes 9505
X-Received-Body-CRC 3376190949
Xref csiph.com comp.lang.python:106439

Show key headers only | View raw


Greetings (again) Ganesh,

I notice that you ask about how to optimize the code, but I think 
what you mean is you want simpler code that is less repetitive and 
less copy/paste error-prone.  Is that correct?

Below, I make a few suggestions about how to simplify, although, 
there probably is further simplification that could be done.

>I am on python 2.7.10 and Linux.

Noted.  I tested my answer to your question on a Python 2.7, as 
well.

>I have a python function where the similar kind of pattern 
>repeating 100 of times

When you have a repetitive sequence of operations (or test cases, it 
looks like), you can often figure out a way to store the parameters 
as data.  When the parameters become data, then, the code becomes 
simpler.

>Sample code snippet:
>
>test01_log = os.path.join(LOG_DIR, "test01.log")
>        cls.get_baddr['test01'] = failure.run_tool(
>            test01_log, object="inode", offset="18", size="4",
>            optype="set")
>
>test02_log = os.path.join(LOG_DIR, "test02.log")
>        cls.get_baddr['test02'] = failure.run_tool(
>            test02_log, lin=lin_02, object="lin", offset="100", size="5",
>            optype="set")
> ..............................................------------------------
>
>test100_log = os.path.join(LOG_DIR, "test100.log")
>        cls.get_baddr['test100'] = failure.run_tool(
>            test02_log, baddr=lin_02, object="baddr", offset="100", size="5",
>            optype="set")

I observe that here in the failure.run_tool() call, the logfile is 
test02_log.  I would have expected it to be test100_log.  I'm 
guessing that this is exactly the sort of copy/paste error that you 
wish to avoid.

>(1)  Any tips how I can optimize this i.e test case, should have a helper
>function that all test cases call.

One function that jumps out very easily (to my eye) is a function to 
create the logfile name from the test case name.  You will see how I 
do that in the sample, so that you can call the run_tool function as 
you are currently calling it.

(You might consider putting the logfile name generation into the 
run_tool function, though, in which case, run_tool gets even simpler 
and you can get rid of my function, addLogFilename.  Hopefully, that 
makes sense to you....)

>(2) Also note that failure.run_tool function can have variable 
>number of argments how to handle this in the helper function?

A variable number of arguments:  this seems like the perfect case 
for using keyword arguments!

  https://docs.python.org/2/tutorial/controlflow.html#keyword-arguments

I have one additional observation about your sample code, Ganesh.  
When I read this:

  cls.get_baddr['test01'] = failure.run_tool(
           test01_log, object="inode", offset="18", size="4",
           optype="set")

I am guessing that you are calling an external program in your test.  
I also notice that you have string contents in your variables, for 
example, offset="18".  (That's part of why I guess you are calling 
an external program as part of your test.)

If you are calling an external command in 'run_tool', why not put 
the exact command-line you want to execute into the test data.  
This would simplify your code and makes the test more transparent, 
as well.

  d = dict()
  d['test01'] = dict(cmd=['some_command', '--offset', '18', '--size', '4'],
                     optype="set", object='inode')

Then, in run_tool, something like this:

  subprocess.Popen(cmd, shell=False, stderr=logfile)

But, these suggestions are all, basically, different riffs on the 
same basic idea:

  Where you have many testing scenarios, try to figure out a way to 
  store all of the test cases in data and then have the test runner 
  operate on the data.

Good luck,

-Martin


#! /usr/bin/python

from __future__ import absolute_import, division, print_function

import os
import sys
import logging


logging.basicConfig(stream=sys.stderr, level=logging.INFO)
logger = logging.getLogger(__name__)

LOG_DIR = '/var/log/frobnitz'


def createTestCases(LOG_DIR):
    '''create a test case data dictionary with parameters'''
    d = dict()
    d['test01'] = dict(object="inode", offset="18", size="4", optype="set")
    lin_02 = "something"
    d['test02'] = dict(object="lin", lin=lin_02, offset="18", size="5",
                       optype="set")
    d['test100'] = dict(object="baddr", baddr=lin_02, offset="100", size="5",
                        optype="set")
    return addLogFilename(d, LOG_DIR)


def run_tool(logfile, **kw):
    logger.info('%s would execute with %r', logfile, kw)


def addLogFilename(d, logdir):
    '''put the logfile name into the test case data dictionary'''
    for casename, args in d.items():
        args['logfile'] = os.path.join(logdir, casename + '.log')
    return d


def main():
    testcases = createTestCases(LOG_DIR)
    get_baddr = dict()
    for casename, kw in testcases.items():
        # -- yank the logfile name out of the dictionary, before calling func
        logfile = kw.pop('logfile')
        get_baddr[casename] = run_tool(logfile, **kw)


if __name__ == '__main__':
    main()

# -- end of file


-- 
Martin A. Brown
http://linux-ip.net/

Back to comp.lang.python | Previous | Next | Find similar | Unroll thread


Thread

Re: how to optimize the below code with a helper function "Martin A. Brown" <martin@linux-ip.net> - 2016-04-04 07:07 -0700

csiph-web