print key into txt file - python

So I am working on a script to generate serialnumbers for a product. I want to make a txt file where I the script prints the generated key. somehow it cant print in there but I don't know what I need to changes about it.
key = Key('aaaa-bbbb-cccc-dddd-1111')
fh = open('key.txt')
fh.write(Key)

Ok, based on your response, I've mocked up the Key class as follows. Without more information, it's not possible to give you a definitive answer, but hopefully this helps!
class Key:
def __init__(self, serial):
self.serial = serial
def process_serial(self):
# Your processing here
...
return processed_serial # This should be a string
Then to write to file, you can do:
key = Key('aaaa-bbbb-cccc-dddd-1111')
with open('key.txt', 'w') as f:
f.write(key.process_serial())
Alternatively, you can add a __str__ method to your class, which will specify what happens when you call the Python builtin str on your object.
class Key:
def __init__(self, serial):
self.serial = serial
def __str__(self):
out = ... # construct what you want to write to file
return out
Giving:
key = Key('aaaa-bbbb-cccc-dddd-1111')
with open('key.txt', 'w') as f:
f.write(str(key))
You might also consider adding this as a method to your Key class
class Key:
__init__(self, serial):
self.serial = serial
def process_serial(self):
# Your processing here
...
return processed_serial # This should be a string
def write(self, file_name):
with open(file_name, 'w') as f:
f.write(self.process_serial)

Try:
key = "Key('aaaa-bbbb-cccc-dddd-1111')"
fh = open('key.txt', "w")
fh.write(key)
To generate a text file that doesn't already exist you need to use "w" .

Try doing:
key = Key('aaaa-bbbb-cccc-dddd-1111')
with open('key.txt', 'w') as fh:
fh.write(key)
Hope that Helps!
Note: it must be in the with ... so it writes, if its not there the file is considered as closed.

Related

Unit testing with external data file in Python

I am new to python and am trying to run unit tests injected with data from an external file:
class TestIsEquivalent(unittest.TestCase):
filename = os.getcwd() + '\\data\\test-data.txt'
with open(filename) as f:
testdata = f.readlines()
for value in testdata:
print(value)
def test_0(self):
result = isEquivalent(value, value, 0)
self.assertEqual(result, True)
I am getting the following error on line isEquivalent() is called with in the test function:
NameError: name 'value' is not defined
This would seem to suggest a scoping issue but I cannot figure out how to pass the value in the for loop into the test method. Any suggestions would be much appreciated.
Your complete test case should be wrapped inside a function. I'm not completely sure what you're trying to do with a function definition inside a for loop, but moving def test_0(self) to the top of your classing does the trick.
class TestIsEquivalent(unittest.TestCase):
def test_0(self):
filename = os.getcwd() + '\\data\\test-data.txt'
with open(filename) as f:
testdata = f.readlines()
for value in testdata:
print(value)
result = isEquivalent(value, value, 0)
self.assertEqual(result, True)
But if you want to create multiple test cases that all you the values inside of testdata, and you dont want to read the file multiple times, you can use the setUpClass function that is executed once at the start of all unittests inside a class. The result would look like this.
class TestIsEquivalent(unittest.TestCase):
#classmethod
def setUpClass(cls):
filename = os.getcwd() + '\\data\\test-data.txt'
with open(filename) as f:
cls.testdata = f.readlines()
def test_0(self):
for value in self.testdata:
print(value)
result = isEquivalent(value, value, 0)
self.assertEqual(result, True)

How to add parameters to an object using variables

I am trying to put some variables into a container (object) using a loop.
I created the following class
class Box():
pass
now i want to initialize the class and add variables from my textfile to it. My textfile looks like:
a = 1
b = 2
c = 3
d = 4
I tried following code
vars = Box()
filename = ('inputfile.txt')
with open (filename) as f:
for line in f:
parts = line.split()
var_name = str(parts[0])
var_value = parts[2]
vars.var_name = var_value
I can't find out why this approach doesn't work.
I think what you are trying to do is use a class as a storage medium for data. As asongtoruin already said, you could use a dictionary.
Otherwise you need to make the class actually something:
class Box():
def __init__(self):
pass
def __getitem__(self, name):
return getattr(self, name)
def __setitem__(self, name, value):
return setattr(self, name, value)
Then you can use almost all of your code as it was:
vars = Box()
filename = ('inputfile.txt')
with open (filename) as f:
for line in f:
parts = line.split()
var_name = str(parts[0])
var_value = parts[2]
vars[var_name] = var_value
print(vars.a)
Why what you had didn't work was already explained by barak manos: vars.var_name does not use the value of the variable var_name, because the syntax calling a class method does not support this notation (for good reason).
When you do
vars.var_name = var_value
it's equal to adding the key 'var_name' to the dict vars.__dict__.
I think what you want can be achieved using setattr.
instead of vars.var_name = var_value, use:
setattr(vars, var_name, var_value)
Maybe try something like
vars[var_name + ''] = var_value
(No python code)
Why don't you use setattr() ?
setattr(Box, "var_name", var_value)

My python function won't write to a file

I've made a function for a flask application to create a decorator and a function and then write them to a file but when I run it, it doesn't create a file and write to it and it doesn't return any errors.
def make_route(title):
route = "#app.route(/%s)" %(title)
def welcome():
return render_template("%s.html" %(title))
return welcome
f = open('test1.txt', 'w')
f.write(route, '/n', welcome, '/n')
f.close()
make_route('Hi')
A return statement terminates execution of the function, so any code after it is ignored. Also, write writes a string, not random objects. You want:
def make_route(title):
route = "#app.route(/%s)" %(title)
def welcome():
return render_template("%s.html" %(title))
with open('test1.txt', 'w') as f:
f.write('%r\n%r\n' % (route, welcome))
return welcome
make_route('Hi')
I would use philhag answer but use %s instead of %r or you'll write a string, and you could use .name if you want to use the function more than once(Which you probably do).
def make_route(title):
route = "#app.route('/%s')" %(title)
def welcome():
return render_template("%s.html" %(title))
with open('test2.py', 'w') as f:
f.write('%s\n%s\n' % (route, welcome))
welcome.__name__ = title
return welcome
make_route('Hi')

Error CSV: coercing to Unicode: need string or buffer, S3BotoStorageFile found

I'm getting the following error when trying to read the row and column count of a CSV:
> coercing to Unicode: need string or buffer, S3BotoStorageFile found
import csv
class CSV:
def __init__(self, file=None):
self.file = file
def read_file(self):
data = []
file_read = read_file(self.file)
return file_read
def get_row_count(self):
return len(self.read_file())
def get_column_count(self):
new_data = self.read_file()
return len(new_data[0])
def get_data(self, rows=1):
data = self.read_file()
return data[:rows]
def read_file(self):
with open(self.file, 'r') as f:
data = [row for row in csv.reader(f.read().splitlines())]
return data
How do I resolve?
well, after reading your code my first reaction was OMG! How many does he open that poor file?
Here's a new version of your class
class CSV:
def __init__(self, file=None):
self.file = file
with open(self.file, 'r') as f:
self.data = [row for row in csv.reader(f)]
def get_row_count(self):
return len(self.data)
def get_column_count(self):
return len(self.data[0])
def get_data(self, rows=1):
return self.data
I also fixed your csv.reader() handling. It accepts a file object, no need to .read() or .read().splitlines(), it can only lead to errors. Which may be the reason why it failed.
Ok, given from what you say, you're working on AWS, and your file is not a string path to a file, but already a file object. So you don't need the open() part as is. You may want to modify your code so it is as follows:
class CSV:
def __init__(self, f=None):
self.file = f
if isinstance(self.file, str): # if the file is a string, it's a path that has to be opened
with open(self.file, 'r') as f:
self.data = [row for row in csv.reader(f)]
elif isinstance(self.file, File) or isinstance(self.file, file): # if that's a file object, no need to open
self.data = [row for row in csv.reader(self.file)]
else: # otherwise, I don't know what to do, so aaaaaaaargh!
raise Exception("File object type unknown: %s %s" % (type(file), file,))
def get_row_count(self):
return len(self.data)
def get_column_count(self):
return len(self.data[0])
def get_data(self, rows=1):
return self.data
Reading the S3BotoStorage.py, the S3BotoStorage class inherits from django.core.files.base.File, which inherits from django.core.files.utils.FileProxyMixin, which is a composition of attributes of the global python file class.
So a File object is not an instance of file, but it has a compatible interface. Therefore, in the previous code I have tested whether the self.file is a str, then it shall be a path that we open() so we get a file() and parse it. Otherwise, self.file is a File object or a file() object, and we just need to parse it. If it's neither of those, then it's an error, and we shall except.

Wrapper to write to multiple streams

In python, is there an easy way to set up a file-like object for writing that is actually backed by multiple output streams? For instance, I want something like this:
file1 = open("file1.txt", "w")
file2 = open("file2.txt", "w")
ostream = OStreamWrapper(file1, file2, sys.stdout)
#Write to both files and stdout at once:
ostream.write("ECHO!")
So what I'm looking for is OStreamWrapper. I know it'd be pretty easy to write my own, but if there's an existing one, I'd rather use that and not have to worry about finding and covering edge cases.
class OStreamWrapper(object):
def __init__(self, *streams):
self.streams = list(streams)
def write(self, string):
for stream in self.streams:
stream.write(string)
def writelines(self, lines):
# If you want to use stream.writelines(), you have
# to convert lines into a list/tuple as it could be
# a generator.
for line in lines:
for stream in self.streams:
stream.write(line)
def flush(self):
for stream in self.streams:
stream.flush()
Way to wrap all public file functions:
import sys
def _call_for_all_streams(func_name):
def wrapper(self, *args, **kwargs):
result = []
for stream in self._streams:
func = getattr(stream, func_name)
result.append(func(*args, **kwargs))
return result
return wrapper
class OStreamWrapper(object):
def __init__(self, *streams):
self._streams = streams
for method in filter(lambda x: not x.startswith('_'), dir(file)):
setattr(OStreamWrapper, method, _call_for_all_streams(method))
if __name__ == '__main__':
file1 = open("file1.txt", "w")
file2 = open("file2.txt", "w")
ostream = OStreamWrapper(file1, file2, sys.stdout)
ostream.write("ECHO!")
ostream.close()
But it's kinda dirty.
Logbook is another option although it is more than that. Its handlers are more powerful and you can combine whatever you like.

Categories