How to prevent code exit during Python 3.6 unit testing [duplicate] - python

This question already has answers here:
Is it possible for a unit test to assert that a method calls sys.exit()?
(4 answers)
Closed 2 years ago.
As I write functions and classes with Python 3.6 I try to write unit tests as soon as I am capable. I am writing a simple function that tests whether or not a file exists at a user-specified location that looks like this:
import os
import sys
import unittest
def verify_file_existance(file_path, file_name):
total_name = file_path + file_name
if os.path.isfile(total_name):
return
sys.exit('{}{}{}'.format('FATAL ERROR: ', file_name, 'does not exist'))
The unit test for the above function looks like
class InputFileTest(unites.TestCase):
def test_verify_file_existance(self):
file_name = 'Test.csv'
file_path = '../../Data/VandV/Input_Reader/'
verify_file_existance(file_path, file_name)
If the file exists at the desired location, the test passes successfully; however, if the file does not exist, the program exits with a Fatal Warning. This is how I want the program to behave during normal operation; however, in unit testing, I want to purposefully be able to place an incorrect path and register that as a successful test, to prove the program does what I want. In other words during one test case, I don't want the program to exit. Is there a way to do this during unit testing?

You can handle the error gracefully using try/except
https://docs.python.org/3/tutorial/errors.html#handling-exceptions
class InputFileTest(unites.TestCase):
def test_verify_file_existance(self):
file_name = 'Test.csv'
file_path = '../../Data/VandV/Input_Reader/'
try:
verify_file_existance(file_path, file_name)
except:
print("file not found")

Try doing try except statements:
class InputFileTest(unites.TestCase):
def test_verify_file_existance(self):
try:
file_name = 'Test.csv'
file_path = '../../Data/VandV/Input_Reader/'
verify_file_existance(file_path, file_name)
except Exception as e:
print("\n\aError. Unable to locate File!\nError: {}").format(str(e))
try:
exit(0)
except:
sys.exit(1)

Related

Correct way to read and write file in python [duplicate]

This question already has answers here:
How to read a file line-by-line into a list?
(28 answers)
Correct way to write line to file?
(17 answers)
Closed 2 years ago.
im writing this function to read from a file and write to another output file, but i recieve no output. Did I write these functions correctly? if they are correct the problem lies within the main body of the decode function, which i will try and sort out.
the code:
def ReadFile(): #Reads data from file
try:
count=0
stringvar=INFILE.open("K:\Data.txt","r")
for line in INFILE:
mylist.append(line.rstrip())
count+=1
INFILE.close()
return count
except:
print("File could not be found")
exit()
writing output file code:
def WriteFile(outlist): #outputs data to output list
OUTFILE=open("Output.txt","a")
for details in outlist:
OUTFILE.write(details+"/n")
parselist.append(a+": Was issued by " +b+ " in "+c+".""The card expires on "+d1+"/"+d2+".The card i linked to" +e+ "with account number:" +f)
OUTFILE.close()
Is there any problem with the code above?
if it will help i will post the whole code ive written.
You usually write to files using the with keyword. We do this so that we can call context managers. Through the use of dundermethods or magic methods we can specify what happens when and if the file does not write or read correctly, so that we'll always be able to close said file if the code fails before being able to do so. Look at this example:
class File:
def __init__(self, file_name, method):
self.file = open(file_name, method)
def __enter__(self):
print("Enter")
return self.file
def __exit__(self, type, value, traceback):
print("Exit")
self.file.close()
with File("file.txt", "w") as f:
print("Middle")
f.write("hello!") #Even if there is an exception and/or we didn't specify a file.close,
#it does so because of the dundermethod we defined in the class.
this is easy fix, just try doing this:
def WriteFile(outlist): #outputs data to output list
with open("Output.txt","a") as OUTFILE:
for details in outlist:
OUTFILE.write(details+"/n")
parselist.append(a+": Was issued by " +b+ " in "+c+".""The card expires on "+d1+"/"+d2+".The card i linked to" +e+ "with account number:" +f)
Just use the with open(...) as ... and it will work, if it throws an error you can try doing: OUTFILE.write(str(details)+"/n") and it will work. hope it helps!

exception stop read files python

I'm trying to control exceptions when reading files, but I have a problem. I'm new to Python, and I am not yet able to control how I can catch an exception and still continue reading text from the files I am accessing. This is my code:
import errno
import sys
class Read:
#FIXME do immutables this 2 const
ROUTE = "d:\Profiles\user\Desktop\\"
EXT = ".txt"
def setFileReaded(self, fileToRead):
content = ""
try:
infile = open(self.ROUTE+fileToRead+self.EXT)
except FileNotFoundError as error:
if error.errno == errno.ENOENT:
print ("File not found, please check the name and try again")
else:
raise
sys.exit()
with infile:
content = infile.read()
infile.close()
return content
And from another class I tell it:
read = Read()
print(read.setFileReaded("verbs"))
print(read.setFileReaded("object"))
print(read.setFileReaded("sites"))
print(read.setFileReaded("texts"))
Buy only print this one:
turn on
connect
plug
File not found, please check the name and try again
And no continue with the next files. How can the program still reading all files?
It's a little difficult to understand exactly what you're asking here, but I'll try and provide some pointers.
sys.exit() will terminate the Python script gracefully. In your code, this is called when the FileNotFoundError exception is caught. Nothing further will be ran after this, because your script will terminate. So none of the other files will be read.
Another thing to point out is that you close the file after reading it, which is not needed when you open it like this:
with open('myfile.txt') as f:
content = f.read()
The file will be closed automatically after the with block.

Integrating exception handling in Python 'with' [duplicate]

This question already has answers here:
Catching an exception while using a Python 'with' statement
(5 answers)
Closed 8 years ago.
A simple way to open a file and read its contents is using with:
with open ('file.txt', "r") as filehandle:
contents = filehandle.read()
But that does not include excepting file opening errors in a way that a try/except would:
try:
filehandle = open('file.txt', 'r')
contents = filehandle.read()
except IOError:
print('There was an error opening the file!')
sys.exit()
Is there a way to integrate a failure message in the with statement so that it exits gracefully if the opening fails that would be done in fewer lines of code than the second example yet provide the same functionality? If not that, is there anything more elegant (or minimalist) than the second form?
from contextlib import contextmanager
#contextmanager
def safe_open(fname,mode):
try:
fh = open(fname,mode)
except IOError:
print "ERROR OPENING FILE :",fname
sys.exit()
else:
yield fh
try:
fh.close()
except:
pass
with safe_open("nofile","rb") as f:
f.write("blah")
Im not sure that its more elegant but meh ...

Stop an operation without stopping the module in python

Well, I have made a module that allows you to copy a file to a directory easier. Now, I also have some "try's" and "except's" in there to make sure it doesn't fail in the big messy way and doesn't close the terminal, but I also want it to display different error messages when a wrong string or variable is put in, and end the module, but not the...if I may say, Terminal running it, so I did this:
def copy():
import shutil
import os
try:
cpy = input("CMD>>> Name of file(with extension): ")
open(cpy, "r")
except:
print("ERROR>>> 02x00 No such file")
try:
dri = input("CMD>>> Name of Directory: ")
os.chdir(dri)
os.chdir("..")
except:
print("ERROR>>> 03x00 No such directory")
try:
shutil.copy(cpy, dri)
except:
print("ERROR>>> 04x00 Command Failure")
Problem is that it doesn't end the module if there is no file or directory, only at the finish.
You may be thinking that when an exception is raised, Python just stops what it's doing, but that's not quite true. The except: block actually catches the exception raised, and is supposed to handle it. After an except: block finishes, Python will continue on executing the rest of the code in the file.
In your case, I'd put a return after each print(...). That way, after Python prints out an error message, it will also return from the copy() function rather than continuing to ask for more input.
If you did want to make the module exit on error...
Here's how you'd do it.
def copy():
import shutil
import os
import sys
try:
cpy = input("CMD>>> Name of file(with extension): ")
open(cpy, "r")
except:
sys.exit("ERROR>>> 02x00 No such file")
try:
dri = input("CMD>>> Name of Directory: ")
os.chdir(dri)
os.chdir("..")
except:
sys.exit("ERROR>>> 03x00 No such directory")
try:
shutil.copy(cpy, dri)
except:
sys.exit("ERROR>>> 04x00 Command Failure")
sys.exit(0) (for success) and sys.exit(1) (for failure) are usually used but, since you want to output the error, the above example will output the error string to stderr.
Here's a link for more info on sys.exit().

Create a temporary FIFO (named pipe) in Python?

How can you create a temporary FIFO (named pipe) in Python? This should work:
import tempfile
temp_file_name = mktemp()
os.mkfifo(temp_file_name)
open(temp_file_name, os.O_WRONLY)
# ... some process, somewhere, will read it ...
However, I'm hesitant because of the big warning in Python Docs 11.6 and potential removal because it's deprecated.
EDIT: It's noteworthy that I've tried tempfile.NamedTemporaryFile (and by extension tempfile.mkstemp), but os.mkfifo throws:
OSError -17: File already exists
when you run it on the files that mkstemp/NamedTemporaryFile have created.
os.mkfifo() will fail with exception OSError: [Errno 17] File exists if the file already exists, so there is no security issue here. The security issue with using tempfile.mktemp() is the race condition where it is possible for an attacker to create a file with the same name before you open it yourself, but since os.mkfifo() fails if the file already exists this is not a problem.
However, since mktemp() is deprecated you shouldn't use it. You can use tempfile.mkdtemp() instead:
import os, tempfile
tmpdir = tempfile.mkdtemp()
filename = os.path.join(tmpdir, 'myfifo')
print filename
try:
os.mkfifo(filename)
except OSError, e:
print "Failed to create FIFO: %s" % e
else:
fifo = open(filename, 'w')
# write stuff to fifo
print >> fifo, "hello"
fifo.close()
os.remove(filename)
os.rmdir(tmpdir)
EDIT: I should make it clear that, just because the mktemp() vulnerability is averted by this, there are still the other usual security issues that need to be considered; e.g. an attacker could create the fifo (if they had suitable permissions) before your program did which could cause your program to crash if errors/exceptions are not properly handled.
You may find it handy to use the following context manager, which creates and removes the temporary file for you:
import os
import tempfile
from contextlib import contextmanager
#contextmanager
def temp_fifo():
"""Context Manager for creating named pipes with temporary names."""
tmpdir = tempfile.mkdtemp()
filename = os.path.join(tmpdir, 'fifo') # Temporary filename
os.mkfifo(filename) # Create FIFO
try:
yield filename
finally:
os.unlink(filename) # Remove file
os.rmdir(tmpdir) # Remove directory
You can use it, for example, like this:
with temp_fifo() as fifo_file:
# Pass the fifo_file filename e.g. to some other process to read from.
# Write something to the pipe
with open(fifo_file, 'w') as f:
f.write("Hello\n")
How about using
d = mkdtemp()
t = os.path.join(d, 'fifo')
If it's for use within your program, and not with any externals, have a look at the Queue module. As an added benefit, python queues are thread-safe.
Effectively, all that mkstemp does is run mktemp in a loop and keeps attempting to exclusively create until it succeeds (see stdlib source code here). You can do the same with os.mkfifo:
import os, errno, tempfile
def mkftemp(*args, **kwargs):
for attempt in xrange(1024):
tpath = tempfile.mktemp(*args, **kwargs)
try:
os.mkfifo(tpath, 0600)
except OSError as e:
if e.errno == errno.EEXIST:
# lets try again
continue
else:
raise
else:
# NOTE: we only return the path because opening with
# os.open here would block indefinitely since there
# isn't anyone on the other end of the fifo.
return tpath
else:
raise IOError(errno.EEXIST, "No usable temporary file name found")
Why not just use mkstemp()?
For example:
import tempfile
import os
handle, filename = tempfile.mkstemp()
os.mkfifo(filename)
writer = open(filename, os.O_WRONLY)
reader = open(filename, os.O_RDONLY)
os.close(handle)

Categories