0

I hope this question makes sense, I have been literally trying to figure this out for two complete days.

I am trying to create a very small script, which I can then convert into a Flask web app, for comparing SPECint processor scores.

A bit of background:

From specint.org, I can download csv files containing benchmark information about processors and servers they have benchmarked. The idea of my app is to do the following:

  1. Ask users for the benchmark they need (cint or rint), the server model, and the processor they're interested in. This must be done twice, for server 1 and server 2 so I can compare them.

  2. I need to check that the information they are entering is correct, i.e. if someone enters as processor name XYZ it should raise an error and prompt for entering a valid query. For this, I'm planning to dump a version of the whole database into my own database, so I can perform the check before actually downloading the csv file from the server.

  3. If the information entered is valid, I would dynamically generate the correct url for downloading and reading the csv file containing the benchmark score information, directly from SPECint's server.

  4. Once I have downloaded and processed the information for both servers, I would apply some simple math and return the results saying something like this: "Server 1 is 10% faster/slower than server 2", or something like that.

As you probably imagine, this will require a lot of duplicated code, so it seems it's the perfect use-case for a class. I have been performing some tests, and the results are promising.

However, my issue is that I have not been able to figure out how to capture the user inputs, test the inputs, download the corresponding csv file, and pass the user inputs all on a per-instance fashion, without having to duplicate code somewhere. I have been searching and searching, and it seems a @classmethod is what I need, but I'm not sure since the use of it still seems quite esoteric to me (I'm a newbie) (ref: Example of Class with User Input)

For example, this is kinda working:

My class:

class Baseline:
    def __init__(self, benchmark, model, processor):
        self.benchmark = benchmark
        self.model = model
        self.processor = processor

Capturing and printing instance results.

old_server = inputs.Baseline(test=input("Select benchmark: "),
                             model=input("Enter model: "),
                             processor=input("Enter processor: ")
                             )
new_server = inputs.Baseline(test=input("Select benchmark: "),
                             model=input("Enter model: "),
                             processor=input("Enter processor: ")
                             )

print(old_server.benchmark)
print(old_server.model)
print(new_server.benchmark)
print(new_server.model)

As you can see, I'm already repeating code, and instead, I'd like to do everything from within the class, so I can simply call instances of it to both capture, test, download, and return the results. As I said earlier, it seems that @classmethodis the answer, but I'd appreciate any guidance, hopefully with a bit of sample code so I can fully grasp the concepts.

bergerg
  • 985
  • 9
  • 23
Edvard Haugland
  • 125
  • 1
  • 9

2 Answers2

0

It was a long question so I hope I followed your drift correctly, If I did you can do something like:

class BaseLine(object):
    @classmethod
    def run(cls):
        benchmark = raw_input('Enter benchmark please: ')
        model = raw_input('Enter model please: ')
        processor = raw_input('Enter processor please: ')

        yes_no = raw_input('you picked %s, %s, %s - are you sure? (y/n) ' % (benchmark, model, processor))

        if yes_no.lower() == 'y':
            print('Great Sucess!')
            return benchmark, model, processor
        else:
            return cls.run()

Where your main would be something like:

benchmark1, model1, processor1 = BaseLine.run()
benchmark2, model2, processor2 = BaseLine.run()

This is a simplified case and depending on the checks you do and how you structure your code you should design if to use a classmethod or an instance method (self). If your instance has a state and your equivalent to run uses that state (connection with DB for instance) then it should be an instance method instead.

Uri Shalit
  • 2,198
  • 2
  • 19
  • 29
  • Cheers Uri. I will try this, and @nutmeg64's answer as well and check which one fits my use case best. I'll report back once I figure it all out :) – Edvard Haugland Oct 15 '17 at 20:11
0

You can do this:

class Baseline:
    def __init__(self):
        self.benchmark = input("Select benchmark: ")
        self.model = input("Enter model: ")
        self.processor = input("Enter processor: ")

Which will make your code less duplicated as creating new instances will be:

old_server = inputs.Baseline()
new_server = inputs.Baseline()

Side note you can also implement the __str__ method to print it all out:

def __str__(self):
    return '\n'.join(str(item) for item in self.__dict__.values())

And then printing is easy:

print(old_server)

As a general advice I wouldn't count on a user's "free" input for processor models and benchmarks since most of the time it contains a mixture of lowercase, uppercase numbers etc.

What I would do, especially because you said you want to use Flask (so thats going to be more simple), is narrow it down to the processor models and benchmarks you support only. Implementation-wise this means a drop-down list on your application and a set or list of the models, benchmarks etc. This will also save you the trouble of input validation.

In the case that not all of the models go with all of the benchmarks you can use dict to do some book-keeping. But if the book-keeping is getting complicated, consider using classes for "automatic" book-keeping. Those classes can then be pickled, jsonified and other methods for saving them into databases.

If you share more code, we could help a little bit more. In any case, I suggest you post this question on code review for deeper analysis.

bergerg
  • 985
  • 9
  • 23
  • This makes a lot of sense. I will try the code and read a bit about what you suggest. I don't have more code to share, unfortunately, pretty much the only code missing so far is the csv reader function. I especially like your suggestion for the implementation, since I'll need that. Creating a dropdown for all options is not really feasible, since they are too many, but dividing them as you suggest is a very good idea. I'm a newbie, so I'll have to do some homework here. Once I have something at least half-functional, I'll submit it to code review. Cheers! – Edvard Haugland Oct 15 '17 at 20:09