i give you an example i click on run write a number in the console(how many keys) and then i get this random letters and numbers: 61PYY-ZEPY1-2H82R-V1JZ1-9VEF7, but i want that they are in my demofile2.txt. when i paste this in the write: '-'.join(''.join(random.choice(seq) for _ in range(5)) for _ in range(5)) it says seq is not definied
This is the code :
import random, sys
class KeyGen():
def __init__(self):
global i
i = int(input("How many serial codes are you looking for? \n"))
print("")
self.main(i)
def main(self, count):
""" Our main iteration function, using simple
capital letters, along with the numbers 0-9 """
seq = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
for i in range(count):
print('-'.join(''.join(random.choice(seq) for _ in range(5)) for _ in range(5)))
print("\nCreated {} serial keys.".format(count))
if __name__ == '__main__':
app = KeyGen()
text_file = open("demofile2.txt.")
text_file.write(THISISWHATISEARCH)
text_file.close()
In order to write to a file you simply need to pass a string to file.write(). In your case the same string you're printing.
One difference is that print automatically adds a new line at the end of each string (because of the default value of the argument end='\n'). So when writing to the file you can add an ending new-line. Alternatively, you can use print's file argument to avoid any change at all!
Now you just need to have the file descriptor available at the point where you want to write to it. That might depend on the design of the rest of your code, for simplicity of the example I will simply move it to the main function.
One more thing is when read/write-ing files, it is better to use the with context manager:
import random, sys
class KeyGen():
def __init__(self):
global i
i = int(input("How many serial codes are you looking for? \n"))
print("")
self.main(i)
def main(self, count):
""" Our main iteration function, using simple
capital letters, along with the numbers 0-9 """
seq = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
with open("demofile2.txt.", 'w') as text_file:
for i in range(count):
print('-'.join(''.join(random.choice(seq) for _ in range(5)) for _ in range(5)), file=text_file)
# text_file.write('-'.join(''.join(random.choice(seq) for _ in range(5)) for _ in range(5)) + '\n')
print("\nCreated {} serial keys.".format(count), file=text_file)
# text_file.write("\nCreated {} serial keys.\n".format(count))
if __name__ == '__main__':
app = KeyGen()
I will use this chance for a general tip:
In Python there is no need to over-use classes. Maybe you come from a Java background where everything is classes, but here your class only serves as a gate-way to a function. So your code could be:
import random, sys
def main():
"""
Our main iteration function, using simple
capital letters, along with the numbers 0-9
"""
seq = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
count = int(input("How many serial codes are you looking for? \n"))
with open("demofile2.txt.", 'w') as text_file:
for _ in range(count):
print('-'.join(''.join(random.choice(seq) for _ in range(5)) for _ in range(5)), file=text_file)
# text_file.write('-'.join(''.join(random.choice(seq) for _ in range(5)) for _ in range(5)) + '\n')
print("\nCreated {} serial keys.".format(count), file=text_file)
# text_file.write("\nCreated {} serial keys.\n".format(count))
if __name__ == '__main__':
main()
Related
Using the library readline I managed to provide tab completion when using input(). My code until now looks like this:
import readline
class TabComplete:
def __init__(self, wordList):
self.wordList = wordList
def complete(self,text,state):
results = [x for x in self.wordList if x.startswith(text)] + [None]
return results[state]
readline.parse_and_bind("tab: complete")
tabComplete = ["IF", "IF_ELSE", "FOR", "WHILE"]
completer = TabComplete(tabComplete)
readline.set_completer(completer.complete)
userTyped = input("prompt > ")
If I start typing I and then hit twice on tab it will propose me IF and IF_ELSE as expected.
What I am searching now is:
if I start typing i and then hit twice tab is there a way to still make it propose IF and IF_ELSE ?
if I type IF EL can I tell him on real time to replace the space by _ so the completion works?
you could always convert your text to upper and replace spaces with "_"
def complete(self,text,state):
text = tex.upper().replace(" ","_")
results = [x for x in self.wordList if x.startswith(text)] + [None]
return results[state]
I'm trying to write a test.py file to test a module I wrote. The specifications of the program are that I take serial user input and then print, not return a single answer. The first line of user input indicates how many inputs will follow. With an example program, "4\n1\n2\n3\n4\n" would mean there are 4 inputs and the inputs are [1,2,3,4]. Here is an example of the program that would take the input (sumEx.py):
import sys
def sum():
n = int(sys.stdin.readline().strip())
nums = []
for _ in range(n):
nums.append(int(sys.stdin.readline().strip()))
result = 0
for num in nums:
result += num
print(result)
if __name__ == "__main__":
sum()
I realize that in this example the for loop is redundant, but this is just an example for the actual program I am working on to abstract the problem. Currently, this is the test file I have:
from io import StringIO
import sys
from _pytest.monkeypatch import MonkeyPatch
import unittest
from sumEx import sum as program
class Testing(unittest.TestCase):
def test_string(self):
monkeypatch = MonkeyPatch()
monkeypatch.setattr('sys.stdin', StringIO("8\n1\n2\n3\n4\n5\n6\n7\n8\n"))
self.assertEqual(program(), 36)
def test_boolean(self):
monkeypatch = MonkeyPatch()
monkeypatch.setattr('sys.stdin', StringIO("4\0\n1\n2\n3\n"))
self.assertEqual(program(), 6)
if __name__ == '__main__':
unittest.main()
The problem is that my tests will only work if I returned them instead of printing them. Ideally, my test file would call the file sumEx.py and then
if __name__ == "__main__":
sum()
would call the sum function, the test would supply the input (like an actual person typing each line), and then whatever sum prints would be considered the output for the test. Any help is greatly appreciated. Please ask any questions if something is too vague. Thank you!
If anyone is curious, this is what I'm gonna go with for now. This takes input from a file and mimics user input through sys.stdin. It then reads the correct output from a file and compares it to the output of the program. It also runs the same test case with different inputs with the help of parameterization. Thank you #MrBeanBremen for the suggestion!
class Testing(unittest.TestCase):
def load_file(self, fileName, inOut):
try:
inputFile = open(fileName, 'r')
fileInput = r'{}'.format(inputFile.readline())
for line in inputFile.readlines():
fileInput = r'{}'.format(fileInput + line)
if inOut == 'in':
fileInput = r'{}'.format(fileInput+'\n')
inputFile.close()
return fileInput
except:
print("ERROR LOADING FILE")
#parameterized.expand([
["./tests/test0in.txt", "./tests/test0out.txt"],
["./tests/test1in.txt", "./tests/test1out.txt"],
["./tests/test2in.txt", "./tests/test2out.txt"]])
#patch('sys.stdout', new_callable=StringIO)
def test(self, inputFile, outputFile, mock_stdout):
monkeypatch = MonkeyPatch()
monkeypatch.setattr('sys.stdin', StringIO(self.load_file(inputFile, "in")))
program.main()
self.assertEqual(mock_stdout.getvalue(), self.load_file(outputFile, "out"))
if __name__ == '__main__':
unittest.main(verbosity=2)
In the example problem below, the main program creates a list of random strings of length data_size. Without multi-processing the data is sent directly to Test.iterate() where the class merely adds the string Test- to the beginning of each random string. When run without multiprocessing the code works very well with small values of data_size and large values of data_size.
I decided to add a multiprocessing ability to this test problem and broke down the core components of multiprocessing into a class title MultiProc. The member function Multiproc.run_processes() manages all functions in the class. The function assumes that the input list will be divided into x smaller lists depending on how many processes the user wishes to utilize. As a result, the function starts by determining the upper and lower indices for each sub-list relative to the initial list so the code knows which portions to iterate over for each thread. The function then initiates the processes, starts the process, joins the process, extracts the data from Queue, then it re-orders the returned data based on a counter that is passed to the primary function. The MultiProc class works fairly well at small values of data_size, but above a value of ~500, the code never terminates, although I suspect the value will vary from computer to computer depending on memory. However, at some point the multiprocess function stops working and I suspect it has something to do with the way data is returned from multiprocess. Does anyone know what might be causing this problem and how to fix it?
from multiprocessing import Process, Queue
from itertools import chain
import string
import random
class Test:
def __init__(self, array_list):
self.array_list = array_list
def func(self, names):
return 'Test-' + names
def iterate(self, upper, lower, counter):
output = [self.func(self.array_list[i]) for i in range(lower, upper)]
return output, counter
class MultiProc:
def __init__(self, num_procs, data_array, func):
self.num_procs = num_procs
self.data_array = data_array
self.func = func
if self.num_procs > len(self.data_array):
self.num_procs = len(self.data_array)
self.length = int((len(self.data_array) / self.num_procs) // 1)
def run_processes(self):
upper = self.__determine_upper_indices()
lower = self.__determine_lower_indices(upper)
p, q = self.__initiate_proc(self.func, upper, lower)
self.__start_thread(p)
self.__join_threads(p)
results = self.__extract_data(q)
new = self.__reorder_data(results)
return new
def __determine_upper_indices(self):
upper = [i * self.length for i in range(1, self.num_procs)]
upper.append(len(self.data_array))
return upper
def __determine_lower_indices(self, upper):
lower = [upper[i] for i in range(len(upper) - 1)]
lower = [0] + lower
return lower
def __initiate_proc(self, func, upper, lower):
q = Queue()
p = [Process(target=self.run_and_send_back_output,
args=(q, func, upper[i], lower[i], i))
for i in range(self.num_procs)]
return p, q
def __start_thread(self, p):
[p[i].start() for i in range(self.num_procs)]
def __join_threads(self, p):
[p[i].join() for i in range(self.num_procs)]
def __extract_data(self, q):
results = []
while not q.empty():
results.extend(q.get())
return results
def __reorder_data(self, results):
new = [results[i - 1] for j in range(self.num_procs)
for i in range(len(results)) if results[i] == j]
new = list(chain.from_iterable(new))
return new
def run_and_send_back_output(self, queue, func, *args):
result = func(*args) # run the func
queue.put(result) # send the result back
def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
if __name__ == "__main__":
random.seed(1234)
data_size = 9
num_proc = 2
test_list = [id_generator() for i in range(data_size)]
obj1 = Test(test_list)
result1 = obj1.iterate(data_size, 0, 1)
print(result1)
multi = MultiProc(num_proc, test_list, obj1.iterate)
result2 = multi.run_processes()
print(result2)
# >> ['Test-2HAFCF', 'Test-GWPBBB', 'Test-W43JFL', 'Test-HA65PE',
# 'Test-83EF6C', 'Test-R9ET4W', 'Test-RPM37B', 'Test-6EAVJ4',
# 'Test-YKDE5K']
Your main problem is this:
self.__start_thread(p)
self.__join_threads(p)
results = self.__extract_data(q)
You start your workers that try to put something in a queue, then join the workers and only after that you start retreiving data from the queue. The workers however can only exit after all data has been flushed to the underlying pipe, and will block on exit otherwise. Joining processes blocked like this before starting to retrieve elements from the pipe can result in a deadlock.
Maybe you should look into multiprocessing.Pool, as what you're trying to implement is some kind of a map() operation. Your example could rewritten more elegantly something like this:
from multiprocessing import Pool
import string
import random
def func(name):
return 'Test-' + name
def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
if __name__ == "__main__":
random.seed(1234)
data_size = 5000
num_proc = 2
test_list = [id_generator() for i in range(data_size)]
with Pool(num_proc) as pool:
result = pool.map(func, test_list)
print(result)
I am trying to create a simple word scrabble script that finds words score values. The script should reads two parameters from the command line and display the best word value, which returns the word with highest point value. I have created a constructor that reads the file and populate a dictionary of letter/value for use with the remaining methods of the class. For example the command line parameters should look like the following:
scrabble.py c:\tiles.txt apple,squash
Output: The best value is squash with 18.
Here is what I have so far. I know that import argv is helful, but not sure how to get started.
from sys import argv
class Scrabble:
def __init__(self, tilesFile):
with open(tilesFile, "r") as f:
lines = [ line.strip().split(":") for line in f ]
self.tiles = { k:int(v) for k,v in lines }
def getWordValue(self, word):
sum = 0
for letter in word.upper():
sum += self.tiles[letter]
return sum
def getBestWord(self):
pass
def main():
s1 = Scrabble("tile_values.txt")
value = s1.getWordValue("hello")
print(value)
if __name__ == '__main__':
main()
pass
What you need is to use the argparse module
https://docs.python.org/3/library/argparse.html
I took your example and added argparse. There are some issues with your Scrabble constructor. But you will get the idea of using args on the command line
python scrabble.py tiles.txt apple squash orange
import argparse
import sys
class Scrabble:
def __init__(self, tilesFile):
with open(tilesFile, "r") as f:
lines = [ line.strip().split(":") for line in f ]
self.tiles = { k:int(v) for k,v in lines }
def getWordValue(self, word):
sum = 0
for letter in word.upper():
sum += self.tiles[letter]
return sum
def getBestWord(self):
pass
def main(argv):
s1 = Scrabble(argv[1])
if len(argv) < 3:
print 'no words given'
sys.exit(1)
# argv[2:] means the items in argv starting from the 3rd item.
# the first item will be the name of the script you are running
# the second item should be the tiles file.
for word in argv[2:]:
value = s1.getWordValue(word)
print(value)
if __name__ == '__main__':
main(argv)
You can get the arguments you script was passed on the command line with sys.argv.
from sys import argv
print("This is a list of all of the command line arguments: ", argv)
I have some problem with sequence generator. I have a file where each line contain one fragment (8 letters). I load it from file in to list, where each element is one fragment. It is DNA so it should go that way:
1. Takes first 8-letter element
2. Check for element in which first 7 letters is the same as last 7 letters in first.
3. Add 8th letter from second element in to sequence.
It should look like this:
ATTGCCAT
TTGCCATA
TGCAATAC
So sequence: ATTGCCATAC
Unfortunately it only add one element. :( First element is given (we knew it). I do it that way its first in file (first line).
Here is the code:
from os import sys
import random
def frag_get(seqfile):
frags = []
f_in = open(seqfile, "r")
for i in f_in.readlines():
frags.append(i.strip())
f_in.close()
return frags
def frag_list_shuffle(frags):
random.shuffle(frags)
return frags
def seq_build(first, frags):
seq = first
for f in frags:
if seq[-7:] == f[:7]:
seq += f[-1:]
return seq
def errors():
pass
if __name__ == "__main__":
frags = frag_get(sys.argv[1])
first = frags[0]
frags.remove(first)
frags = frag_list_shuffle(frags)
seq = seq_build(first, frags)
check(sys.argv[2], seq)
spectrum(sys.argv[2], sys.argv[3])
I have deleted check and spectrum functions because it's simple calculations e.g. length comparison, so it is not what cause a problem as I think.
I will be very thankfully for help!
Regards,
Mateusz
Because your fragments are shuffled, your algorithm needs to take that into account; currently, you're just looping through the fragments once, which is unlikely to include more than a few fragments if they're not in the right order. For example, say you have 5 fragments, which I'm going to refer to by their order in your sequence. Now the fragments are slightly out of order:
1 - 3 - 2 - 4 - 5
Your algorithm will start with 1, skip 3, then match on 2, adding a base at the end. Then it'll check against 4 and 5, and then finish, never reaching fragment 3.
You could easily fix this by starting your loop again each time you add a base, however, this will scale very badly for a large number of bases. Instead, I'd recommend loading your fragments into a trie, and then searching the trie for the next fragment each time you add a base, until you've added one base for each fragment or you can no longer find a matching fragment.
works for me:
>>> seq = "ATTGCCAT"
>>> frags = ["TTGCCATA", "TGCCATAC"]
>>> for f in frags:
... if seq[-7:] == f[:7]:
... seq += f[-1:]
...
>>> seq
'ATTGCCATAC'
You have a spelling error in your example, TGCAATAC should be TGCCATAC. But fixing that it works.
For fun and interest, I've rewritten the problem using OO. See what you think:
import collections
import sys
import random
usage = """
Usage:
sequence fname expected
Where
fname: name of file containing fragments
expected: result-string which should be obtained by chaining from first fragment.
"""
class Frag(str):
MATCHLEN = 7
def __new__(cls, s=''):
return str.__new__(cls, s.strip())
def head(self):
return Frag(self[:Frag.MATCHLEN])
def tail(self):
return Frag(self[Frag.MATCHLEN:])
def nexthead(self):
return Frag(self[-Frag.MATCHLEN:])
def check(self, s):
return self.__eq__(s)
def __add__(self, s):
return Frag(str(self).__add__(s))
class Fraglist(list):
#classmethod
def fromFile(cls, fname):
with open(fname, "r") as inf:
lst = [Frag(ln) for ln in inf]
return cls(lst)
def shuffle(self):
random.shuffle(self)
class Sequencer(object):
def __init__(self, seq=None):
super(Sequencer, self).__init__()
self.sequences = collections.defaultdict(list)
if seq is not None:
for frag in seq:
self.sequences[frag.head()].append(frag.tail())
def build(self, frag):
res = [frag]
match = frag.nexthead()
while match in self.sequences:
next = random.choice(self.sequences[match])
res.append(next)
match = (match + next).nexthead()
return Frag(''.join(res))
def main():
if len(sys.argv) != 3:
print usage
sys.exit(-1)
else:
fname = sys.argv[1]
expected = sys.argv[2]
frags = Fraglist.fromFile(fname)
frag1 = frags.pop(0)
frags.shuffle()
seq = Sequencer(frags)
result = seq.build(frag1)
if result.check(expected):
print "Match!"
else:
print "No match"
if __name__=="__main__":
main()