Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This is a simple example of script to run the test write/read performance of third party software of the drive in Windows environment.

Please let me know if you find any place can be better improved, thanks.

#! /usr/bin/env python

import sys, os
import PCMark 
import PCMTest
from decimal import Decimal
import re
import time

class PCMark(PCMTest) :

    DesktopInteractive = True

    def __init__(self, cliArgs=[],logger=None) :
        PCMTest.__init__(self, cliArgs=cliArgs,logger=logger,subclassName=name) 

    def _run(self):
        pcm = PCMark(self.logger)

        counter = 0
        readScore = 0
        readScores = []
        writeScores = []
        rdReadScores = []
        rdWriteScores = []
        rndReadScores = []
        rndWrt4Scores = []
        rndRd32Scores = []
        rndWrt32Scores = []


        while counter < 3:
            #self.logger.info("Sleeping for 3 minutes before starting the PCM")
            #time.sleep(60*3)

            counter = counter + 1
            self.resultsFile = PCM.run(3,10)

            #PCM1
            ReadResults = re.findall("Read :.*\d*\.\d* ",self.resultsFile)[0]       
            readScore = self.getNumber(seqReadResults)
            readScores.append(readScore)

            #PCM2
            writeResults = re.findall("Write :.*\d*\.\d* ",self.resultsFile)[0]          
            writeScore = self.getNumber(writeResults)
            writeScores.append(writeScore)

            #PCM3
            rdWriteResults = re.findall("#3 Read:.*\d*\.\d* ",self.resultsFile)[0]          
            rdWriteScore = self.getNumber(rdWriteResults)
            rdReadScores.append(rdWriteScore)   

            #PCM4
            rdWriteResults = re.findall("#4 Write :.*\d*\.\d* ",self.resultsFile)[0]          
            rdWriteScore = self.getNumber(rdWriteResults)
            rdWriteScores.append(rdWriteScore)                               

        for score in readScores:
            self.logger.info("Read score was: "+ str(score) + "")

        averagereadScore = self.averageScores(readScores)    
        self.logger.info("Avg #1 read:" + str(averagereadScore))
        if self.checkScores(readScores,averagereadScore): 
            self.logger.info("Passed because the score was good.")    
        else: 
            self.testFailed("Failing because average score was too low.",False)     

        for score in writeScores:
            self.logger.info("Write score was: "+ str(score))

        averagewriteScore = self.averageScores(writeScores)    
        self.logger.info("Average Sequential Write speed was:" + str(averagewriteScore))
        if self.checkScores(writeScores,averagewriteScore): 
            self.logger.info("Passed because the score was good.")    
        else: 
            self.testFailed("Failing because average score was too low.",False)   

        #read
        for score in rdReadScores:
            self.logger.info("Rd score was: "+ str(score))

        averagerdWriteScore = self.averageScores(rdReadScores)    
        self.logger.info("Average rd score was:" + str(averagerdWriteScore))
        if self.checkScores(rdReadScores,averagerdWriteScore): 
            self.logger.info("Passed because the score was good.")    
        else: 
            self.testFailed("Failing because average score was too low.",False)   

        # write
        for score in rdWriteScores:
            self.logger.info("Wrt score was: "+ str(score))

        averagerdWriteScore = self.averageScores(rdWriteScores)    
        self.logger.info("Average wrt score was " + str(averagerdWriteScore))
        if self.checkScores(rdWriteScores,averagerdWriteScore): 
            self.logger.info("Passed because the score was good.")    
        else: 
            self.testFailed("Failing because average score was too low.",False)   



    def averageScores(self, scores):
        total = 0
        error = 0
        for score in scores:
            total = total + score
            if score == 0:
                error =1
        averageScores = total / len(scores)
        return float(averageScores)

    def getNumber(self, results):
        numbers = 0
        numbers = float(re.findall("\d*\.\d*",results)[0])
        return float(numbers)

    def checkScores(self, scores, average):
        min = average * .01
        self.logger.info("Min limit is: %.0i" %min)
        for score in scores: 
            if score < min: 
                self.logger.info("Score is too low:" + str(score))
                return False
        return True


if __name__ == "__main__":

    Main()
share|improve this question

closed as unclear what you're asking by 200_success May 19 at 6:52

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question.If this question can be reworded to fit the rules in the help center, please edit the question.

    
Recent revisions of this question do not appear to contain working code. – 200_success May 19 at 6:53

I’m not familiar with the libraries that you’re using, but I can give some feedback on your general Python style:

  • In Python, variable names are lowercase_with_underscores, not dromedaryCase. The exception is class names, which are PascalCase.
  • There are very few comments or docstrings, which makes it hard to follow or debug your program.
  • The convention is that lines should be wrapped to 79 characters, except comments and docstrings, which should be wrapped to 72.
  • In the __init__ constructor, you call PCMTest.__init__ directly, where PCMTestis the class that you’re subclassing. The better way to do it is to use super(); that is

    super(PCMark).__init__(self, ...)
    

    Now if you change what you’re subclassing, you don’t need to change the constructor.

    See super() considered super() for more background on this.

  • There’s no need to use a while loop to repeat your tests three times with the counter variable. Much better to use a for loop:

    for _ in range(3):  # or xrange(3) if you're using Python 2
        do_stuff()
    

    Note also that I’ve used underscore for a variable name – this is a convention that means “the value of this variable is unimportant, it’s just for looping”. It makes your intent clearer to other programmers.

  • You have this code for sleeping which is commented out:

    self.logger.info("Sleeping for 3 minutes before starting the CDM")
    time.sleep(60*3)
    

    It would be easy for the log message to get out of sync with reality, if somebody changes the sleep() call but not the log. You can mitigate this by pulling the number of minutes to sleep out into a variable:

    minutes_to_sleep = 3
    self.logger.info('Sleeping for %d minutes before starting the CDM',
                     minutes_to_sleep)
    time.sleep(60 * minutes_to_sleep)
    

    Not only is that less likely to fall out of sync, it also makes it clearer to future users how to modify this variable.

  • Within the loop, you make a lot of repeated calls of the form

    results = re.findall('<some string>', self.resultsFile)[0]
    score = self.getNumber(results)
    

    Have you considered pulling that out into a function that goes straight to the score? That would cover up a bit of complexity, and probably make your code easier to read.

  • You create log messages using string concatenation; for example:

    self.logger.info("Read score was: "+ str(score) + "MB/s")
    

    First, you should never use string concatenation: you should use new-style .format() strings.

    Second, if you have variables like this in logs, you should use format tokens, and supply the parameters as extra arguments to the log; i.e.,

    self.logger.info('Sequential read score was: %d MB/s', score)
    

    Now the logging module will only substitute your variable if it’s actually going to write the log. If this message never gets logged (because the logging level is too high), you just saved a bit of work by not substituting this string.

  • In averageScores, you create but never use the error variable. What's that for? You can also do away with the total and averageScores variable; as follows:

    def average_scores(self, scores):
        return float(sum(scores)) / len(scores)
    

    Note that if you want the true average, you need to cast to float() when you do the division. In Python 2.7, integer division is floor division, so the information was already lost.

    Note also that this function will throw a ZeroDivisionError if you pass in an empty list of scores -- so be careful of that!

  • There is no reason to initialise the numbers variable with 0 in getNumber().

  • In checkScores(), you could simply the final check as follows:

    if score < mymin:
         self.logger.info(Score is too low:" + str(score))
         return False
    

    Note also that I’ve changed the variables of min and max, as those are builtins. Shadowing builtin function names will cause subtle and annoying bugs; just don’t do it.

share|improve this answer

Here, instead of another regex in getNumber

        seqReadResults = re.findall("Sequential Read :.*\d*\.\d* MB/s",self.resultsFile)[0]       
        seqReadScore = self.getNumber(seqReadResults)

you could use a capturing group in the first regex:

        seqReadResults = re.findall("Sequential Read :.*(\d*\.\d*) MB/s",self.resultsFile)[0]       
        seqReadScore = float(seqReadResults)
share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.