This question already has answers here:
How can I get new results from randint while in a loop?
(2 answers)
Closed 3 years ago.
I am able to generate random hex values in a specific range using the code below, but I get the same random value on each line if i set my counter to more than 1. I'm guessing I need a loop, I have tried with "for x in range" but my implementation must be wrong as it overflows. I'm new to python and have searched for days but can't seem to find how to implement it correctly.
import random
import sys
#ran = random.randrange(2**64)
ran = random.randrange(0x8000000000000000, 0xFFFFFFFFFFFFFFFF)
myhex = "%064x" % ran
#limit string to 64 characters
myhex = myhex[:64]
counter = 0
file = open('output.txt', 'w')
sys.stdout = file
for result in myhex:
print(myhex)
counter += 1
if counter > 10:
break
As pointed out in the comments, you're generating the random number only once. To have a new random value for each iteration, you need to put the generation code in the loop as follows:
# ... your imports
with open('output.txt', 'w') as f:
for _ in range(10):
ran = random.randrange(0x8000000000000000, 0xFFFFFFFFFFFFFFFF)
myhex = "%064x" % ran
#limit string to 64 characters
myhex = myhex[:64]
f.write(myhex)
f.write("\n")
Also, if you want to dump the results in a file, a better approach is to write directly to the file without changing sys.stdout, as done in the above code.
Related
I have a code that generates characters from 000000000000 to ffffffffffff which are written to a file.
I'm trying to implement a check to see if the program was closed so that I can read from the file, let's say at 00000000781B, and continue for-loop from the file.
The Variable "attempt" in (for attempt in to_attempt:) has tuple type and always starting from zero.
Is it possible to continue the for-loop from the specified value?
import itertools
f = open("G:/empty/last.txt", "r")
lines = f.readlines()
rand_string = str(lines[0])
f.close()
letters = '0123456789ABCDEF'
print(rand_string)
for length in range(1, 20):
to_attempt = itertools.product(letters, repeat=length)
for attempt in to_attempt:
gen_string = rand_string[length:] + ''.join(attempt)
print(gen_string)
You have to store the value on a file to keep track of what value was last being read from. I'm assuming the main for loop running from 000000000000 to ffffffffffff is the to_attempt one. All you need store the value of the for loop in a file. You can use a new variable to keep track of it.
try:
with open('save.txt','r') as reader:
save = int(reader.read())
except FileNotFoundError:
save = 0
#rest of the code
for i in range(save,len(to_attempt)):
with open('save.txt','r') as writer:
writer.write(i)
#rest of the code
Exporting the data:
num = 0
exportData = open("results_file.txt", "a")
while num < len(runs) - 1:
exportData.write(str(runs[num]) + "\n")
num = num + 1
exportData.close()
Importing the data into the new file:
runs = []
num = 1
count = len(open("results_file.txt").readlines( ))
print(count)
importData = open("results_file.txt", "r")
while num < count:
runs.append(importData.read(num))
print(importData.read(num))
num = num + 1
importData.close()
My goal is to export the array of integers to a file (can be something else than a txt file for all I care) and then to import them at a later date into a new file and use them there as integers (performing mathematical operations on them)
The error that I'm getting (on line 28 I'm trying to use the first number in the array for a mathematical calculation):
line 28, in if runs[num] < 7: TypeError: '<' not supported between instances of 'str' and 'int'
runs = []
num = 1
count = len(open("results_file.txt").readlines( ))
print(count)
importData = open("results_file.txt", "r")
while num < count:
runs.append(int(importData.read(num)))
print(importData.read(num))
num = num + 1
importData.close()
Adding int() returns this error:
ValueError: invalid literal for int() with base 10: '4\n1'
You're not being pythonic, and many of the answers here aren't either. So, let me clean up your code a bit.
from ast import literal_eval
with open("results_file.txt", "a") as exportData:
for run in runs:
exportData.write(str(run) + "\n")
runs = []
with open("results_file.txt", "r") as importData:
runs.extend([literal_eval(x) for x in importData])
I'll break this down line by line:
from ast import literal_eval is the safest way to parse things that are strings into python objects. It's better than using a plain old eval because it won't run arbitrary code. We'll use this function to read the data latter.
with open(...) as ... is the best way to open a file. It contains the file-object within a single scope and catches errors. Look this one up here: Pep 343
for ... in ... For loops that you're using are not pythonoic at all. The pythonic way is to use iterators no need to count lines and declare variables to keep track... the python objects keep track of themselves. (If you need a counter I highly recommend that you look up enumerate() Enumerate() in Python
exportData.write(str(run) + "\n") only change here is that with the pythonic for loop there's no need to index the runs list anymore.
runs = [] I think you know what this is, but I have to declare it out of the with statement because if the with statement throws an error, and you were to catch it, runs will be initialized.
I've already discussed with statements.
runs.extend([literal_eval(x) for x in importData]) Has two things going on. extend appends a list to a list... cool. The more interesting part here is the list comprehension. Here's a tutorial on list comprehensions. As soon as you get comfortable with the for loops, the list comprehension is the next pythonic step. For further pythonic enlightenment, this line could also be replaced with: runs.extend(map(literal_eval, importData))
That's it, 9 lines. Happy hacking.
The error you are experiencing is most likely due to the fact you're trying to add a string to an integer. Try doing
runs = []
num = 1
count = len(open("results_file.txt").readlines( ))
print(count)
importData = open("results_file.txt", "r")
while num < count:
runs.append(int(importData.read(num)))
print(importData.read(num))
num = num + 1
importData.close()
The main function/tool you're looking for is int(). For example:
>>> int('15')
15
>>> int('15') + 5
20
But you also can save yourself some real headaches by coding this differently. For example, you do not need to know the number of lines ahead of time. You can just call .readline() until it returns an empty string. Or even iterate over the file and when it ends, it with exit.
Another tip, and this is just good practice, is to use the context manager for opening files. So instead of
file = open('myfile.txt')
for line in file:
print(line)
you would do:
with open('myfile.txt') as file:
for line in file:
print(line)
The big advantage of the latter is that if will always make sure file is closed properly. This is especially helpful when writing to a file.
so for class we have to start out our problem doing this:
Write a function that takes as its input a filename, and an integer. The file should open the file and read in the first number of lines given as the second argument. (You'll need to have a variable to use as a counter for this part).
It's very basic and I figure a loop is needed but I can't figure out how to incorporate a loop into the question. What I've tried doesn't work and it's been about 3 hours and the best I can come up with is
def filewrite(textfile,line):
infile=open(textfile,'r',encoding='utf-8')
text=infile.readline(line)
print(text)
however that doesn't get me to what I need for the function. It's still early in my intro to python class so basic code is all we have worked with.
There are two basic looping strategies you could use here:
you could count up to n, reading lines as you go
you could read lines from file, keeping track of how many you've read, and stop when you reach a certain number.
def filewrite(textfile, n):
with open(textfile) as infile:
for _ in range(n):
print(infile.readline(), end='')
print()
def filewrite(textfile, n):
with open(textfile) as infile:
counter = 0
for line in infile:
if counter >= n:
break
print(line, end='')
counter += 1
The first is obviously more readable, and since readline will just return an empty string if it runs out of lines, it's safe to use even if the user asks for more lines than the infile has.
Here I'm also using a context manager to make sure the files are closed when I'm done with them.
Here's a version without the stuff you don't recognize
def filewrite(textfile, n):
infile = open(textfile)
count = 0
while count < n:
print(infile.readline())
count += 1
infile.close()
count = 1
maxcount = 6
while(count <= maxcount):
print locals()["test_"+str(count)]+str(".png")
count += 1
I was hoping for the output
test_1.png
test_2.png
test_3.png
test_4.png
test_5.png
test_6.png
Instead I get an error
KeyError: 'test_1'
Also, is it possible to add a 0 after the _ if the value is less than 10?
I am using this loop for saving files, but figured that this MWE would be less labour and would easily apply to my issue
You are getting that error because you have not created a variable named 'test_1' in your local scope. Instead of using a while loop, it is easier to use a for loop. Also, there's a thing called string formatting, which is easier to use than string concatenation.
maxcount = 6
for i in range(1, maxcount+1):
filename = 'test_{}.png'.format(i)
with open(filename, 'r') as f:
# do stuff
This question already has answers here:
Length of generator output [duplicate]
(9 answers)
How to look ahead one element (peek) in a Python generator?
(18 answers)
How to print a generator expression?
(8 answers)
Closed 8 years ago.
Yesterday I have been implementing a small Python scripts that checks difference between two files (using difflib), printing the result if there is any, exiting with code 0 otherwise.
The precise method, difflib.unified_diff() is returning a generator on the diffs found. How can I test this generator to see if it needs to be printed? I tried using len(), sum() to see what was the size of this generator but then it is impossible to print it.
Sorry to ask such a silly question but I really don't see what is the good practice on that topic.
So far this is what I am doing
import difflib
import sys
fromlines = open("A.csv").readlines()
tolines = open("B.csv").readlines()
diff = difflib.unified_diff(fromlines, tolines, n=0)
if (len(list(diff))):
print("Differences found!")
# Recomputing the generator again: how stupid is that!
diff = difflib.unified_diff(fromlines, tolines, n=0)
sys.stdout.writelines(diff)
else:
print("OK!")
You're already converting your generator to a list, so you don't need to rebuild it.
diff = list(difflib.unified_diff(fromlines, tolines, n=0))
if diff:
...
sys.stdout.writelines(diff)
else:
...
You don't even need to convert the generator to a list if you don't want by using a simple flag:
diff = difflib.unified_diff(fromlines, tolines, n=0)
f = False
for line in diff:
if not f:
print("Differences found!")
f = True
sys.stdout.write(line)
if not f:
print("OK!")
You could convert the generator into a list.
diff = list(difflib.unified_diff(fromlines, tolines, n=0))
I think you can't, and the proper way is probably to generate all data until you raise StopIteration and then get the length of what you have generated.
What's wrong with :
import difflib
import sys
fromlines = open("A.csv").readlines()
tolines = open("B.csv").readlines()
diff = difflib.unified_diff(fromlines, tolines, n=0)
difflines = list(diff)
if len(difflines) :
sys.stdout.writelines(difflines)
else:
print("OK!")