2

I have a class that creates a "Test" object - an object based on (describes) an external test script.

The code can be found here: https://codeshare.io/5zlW0W

I use this class like this:

from test import Test

test = Test("/path/to/test")

This works perfectly well when the test file exists, but I hit the following error when it does not exist:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/user/repos/test.py", line 13, in __init__
    self.version = self.get_attribute("version")
  File "/home/user/repos/test.py", line 33, in get_attribute
    p = subprocess.Popen([self.path, '--' + attribute], stdout=subprocess.PIPE, universal_newlines=True)
  File "/usr/lib/python3.5/subprocess.py", line 947, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.5/subprocess.py", line 1551, in _execute_child
    raise child_exception_type(errno_num, err_msg)
FileNotFoundError: [Errno 2] No such file or directory: 'bla'

So my question comes in two parts:

  1. What is the best way to handle the case where the path does not exist?
  2. Is it okay for me to define the initial variable using functions to grab that data as I have done in __init__?
Dan D.
  • 73,243
  • 15
  • 104
  • 123
Cov
  • 561
  • 5
  • 20
  • Well, what do you want to happen if the file doesn't exist? A proper error message instead of an Exception? The file being created? (If so, with what content?) – das-g Apr 06 '17 at 09:40
  • @das-g Ideally I would like the object not to be initialised if the file cannot be found. – Cov Apr 06 '17 at 09:41

2 Answers2

3

Check the file exist in the get_attribute method by using os.path.exists(file_path)

def get_attribute(self, attribute):
        """Return a given attribute of the test.

        Runs a test subprocess with the --<attribute> argument.
        """
        if os.path.exists(self.path):
            p = subprocess.Popen([self.path, '--' + attribute], stdout=subprocess.PIPE, universal_newlines=True)
                attr = p.stdout.read().strip("\n")

            return attr
Surajano
  • 2,688
  • 13
  • 25
0

You could always use the standard OS library.

import os
from test import Test

if os.path.exists("/path/to/test"):
    test = Test("/path/to/test")

If you also wish to make sure the file is not empty, you can use

if os.stat("/path/to/test").st_size > 0:

Note this may cause race condition:

A good question regarding this matter may be found here: How does using the try statement avoid a race condition?

Community
  • 1
  • 1
Ilhicas
  • 1,429
  • 1
  • 19
  • 26
  • 1
    Using `os.path.exists` (same applies to `os.stat`) will result in a test-use race. It is better to have open fail and catch the exception and throw your own. – Dan D. Apr 06 '17 at 09:56
  • @DanD. Sorry, could you expand on what that means please (test-use race)? – Cov Apr 06 '17 at 09:58
  • Thank you for you comment Dan, was giving op another option but you are correct. – Ilhicas Apr 06 '17 at 09:59
  • 1
    @Sithling I had reduced TOCTOU race to test-use race which no one else did. See https://en.wikipedia.org/wiki/Time_of_check_to_time_of_use – Dan D. Apr 06 '17 at 10:03
  • 1
    @Sithling , you can always refer to this question to see why it may cause a race condition, and if it would be possible in your scenario http://stackoverflow.com/questions/14574518/how-does-using-the-try-statement-avoid-a-race-condition – Ilhicas Apr 06 '17 at 10:04