I'm writing a python program. The program calculates Latin Squares using two numbers the user enters on a previous page. But but an error keeps coming up, "cannot concatenate 'str' and 'list' objects" here is the program:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# enable debugging
import cgi
import cgitb
cgitb.enable()
def template(file, **vars):
return open(file, 'r').read() % vars
print "Content-type: text/html\n"
print
form = cgi.FieldStorage() # instantiate only once!
num_1 = form.getfirst('num_1')
num_2 = form.getfirst('num_2')
int1r = str(num_1)
int2r = str(num_2)
def calc_range(int2r, int1r):
start = range(int2r, int1r + 1)
end = range(1, int2r)
return start+end
int1 = int(int1r)
int2 = int(int2r)
out_str = ''
for i in range(0, int1):
first_line_num = (int2 + i) % int1
if first_line_num == 0:
first_line_num = int1
line = calc_range(first_line_num, int1)
out_str += line
print template('results.html', output=out_str, title="Latin Squares")
range returns a list object, so when you say
line = calc_range(first_line_num, int1)
You are assigning a list to line. This is why out_str += line throws the error.
You can use str() to convert a list to a string, or you can build up a string a different way to get the results you are looking for.
By doing out_str += line, you're trying to add a list (from calc_range) to a string. I don't even know what this is supposed to be doing, but that's where the problem lies.
You didn't say what line you're getting the error from, but I'm guessing it's:
out_str += line
The first variable is a string. The second is a list of numbers. You can't concatenate a list onto a string. I don't know what you're trying to do exactly, but how about:
out_str += ", ".join(line)
That will add the numbers joined by commas onto out_str.
calc_range() returns a list; however, you are attempting to add it to a string (out_str).
It looks like your code is unfinished - don't you want to do something with the range of numbers returned by calc_range()? Like, say, something with the form?
line = ''.join(num_1[index] for index in calc_range(first_line_num, int1))
I don't know if that's what you want - but maybe something like that?
Related
I'm making a python that changes lines through arguments, but it's giving an error:
TypeError: list indices must be integers or slices, not str
Script:
import os
import sys
from pathlib import Path
pathh = os.path.basename(__file__)
pathhh = pathh.replace("py", "exe")
path_to_file = f'{sys.argv[1]}'
path = Path(path_to_file)
if path.is_file():
if len(sys.argv) > 1:
def replace_line(file_name, line_num, text):
lines = open(file_name, 'r').readlines()
lines[line_num] = text
out = open(file_name, 'w')
out.writelines(lines)
out.close()
my_list = [f'{sys.argv[1]}', f'{sys.argv[2]}', f'{sys.argv[3]}']
my_str = '0'
my_str2 = '1'
my_str3 = '2'
result = my_list[int(my_str)]
result1 = my_list[int(my_str2)]
result2 = my_list[int(my_str3)]
replace_line(f'{result}', f'{result1}', f'{result2}')
else:
print(f"Usage: {pathh} <File> <LINE> <TOEDIT>")
print("This program was made by CookieYT#9267")
else:
print(f"Usage: {pathh} <File> <LINE> <TOEDIT>")
print("This program was made by CookieYT#9267")
I've tried several ways, and nothing
Does anyone know how to solve it?
The line_num argument to replace_line() is supposed to be an integer, so you can use it in lines[line_num]. So don't format it as a string when you call the function.
There's no need to put the other arguments in f-strings, either, since they're already strings.
replace_line(result, result1, result2)
Similarly, all the elements of sys.argv are strings, you don't need to put them in f-strings, either. So you should write
my_list = sys.argv[1:4]
And if you just want to convert a variable to a string, use str(variable) rather than f'{variable}'. They're equivalent, but str() is the more common idiom. F-strings should be used when you need to add more formatting text, combine multiple variables, or need to specify formatting options (e.g. field size, justification, number of decimal places, etc.).
I need this program to create a sheet as a list of strings of ' ' chars and distribute text strings (from a list) into it. I have already coded return statements in python 3 but this one keeps giving
return(riplns)
^
SyntaxError: invalid syntax
It's the return(riplns) on line 39. I want the function to create a number of random numbers (randint) inside a range built around another randint, coming from the function ripimg() that calls this one.
I see clearly where the program declares the list I want this return() to give me. I know its type. I see where I feed variables (of the int type) to it, through .append(). I know from internet research that SyntaxErrors on python's return() functions usually come from mistype but it doesn't seem the case.
#loads the asciified image ("/home/userX/Documents/Programmazione/Python projects/imgascii/myascify/ascimg4")
#creates a sheet "foglio1", same number of lines as the asciified image, and distributes text on it on a randomised line
#create the sheet foglio1
def create():
ref = open("/home/userX/Documents/Programmazione/Python projects/imgascii/myascify/ascimg4")
charcount = ""
field = []
for line in ref:
for c in line:
if c != '\n':
charcount += ' '
if c == '\n':
charcount += '*' #<--- YOU GONNA NEED TO MAKE THIS A SPACE IN A FOLLOWING FUNCTION IN THE WRITER.PY PROGRAM
for i in range(50):#<------- VALUE ADJUSTMENT FROM WRITER.PY GOES HERE(default : 50):
charcount += ' '
charcount += '\n'
break
for line in ref:
field.append(charcount)
return(field)
#turn text in a list of lines and trasforms the lines in a list of strings
def poemln():
txt = open("/home/gcg/Documents/Programmazione/Python projects/imgascii/writer/poem")
arrays = []
for line in txt:
arrays.append(line)
txt.close()
return(arrays)
#rander is to be called in ripimg()
def rander(rando, fldepth):
riplns = []
for i in range(fldepth):
riplns.append(randint((rando)-1,(rando)+1)
return(riplns) #<---- THIS RETURN GIVES SyntaxError upon execution
#opens a rip on the side of the image.
def ripimg():
upmost = randint(160, 168)
positions = []
fldepth = 52 #<-----value is manually input as in DISTRIB function.
positions = rander(upmost,fldepth)
return(positions)
I omitted the rest of the program, I believe these functions are enough to get the idea, please tell me if I need to add more.
You have incomplete set of previous line's parenthesis .
In this line:-
riplns.append(randint((rando)-1,(rando)+1)
You have to add one more brace at the end. This was causing error because python was reading things continuously and thought return statement to be a part of previous uncompleted line.
I wrote a code that will generate random password for 5 times, and I would like to encode that passwords to MD5, but when I try to encode it, it will show an error that 'NoneType' object has no attribute 'encode' and I dont know how to change the code to avoid this error. Sorry I'm beginner in python... My Code is below. Thanks for help
import random, string
import hashlib
length = 6
chars = string.ascii_letters + string.digits
def ff():
rnd = random.SystemRandom()
a = (''.join(rnd.choice(chars) for i in range(length)))
c = a
return(c)
def ff2():
for i in range(5):
print(ff(),' ')
str = ff2()
result = hashlib.md5(str.encode())
print("The hexadecimal equivalent of hash is : ", end ="")
print(result.hexdigest())
The function ff2 doesn’t return anything so str will be of type NoneType.
IIUC, your ff2() function should call ff() five times but it should not print out the result. It should accumulate them in a string and return the string. Something like this perhaps:
def ff2():
l = []
for i in range(5):
l.append(ff())
return " ".join(l)
Here we accumulate the results of the five calls to ff() in a list l and then
use the string method join() to join them together.
The above returns a string that is the concatenation of the five strings that the calls to ff() returned, with spaces separating them. If you want commas as separators, just replace the return " ".join(l) with return ",".join(l).
I'm trying to read a null terminated string but i'm having issues when unpacking a char and putting it together with a string.
This is the code:
def readString(f):
str = ''
while True:
char = readChar(f)
str = str.join(char)
if (hex(ord(char))) == '0x0':
break
return str
def readChar(f):
char = unpack('c',f.read(1))[0]
return char
Now this is giving me this error:
TypeError: sequence item 0: expected str instance, int found
I'm also trying the following:
char = unpack('c',f.read(1)).decode("ascii")
But it throws me:
AttributeError: 'tuple' object has no attribute 'decode'
I don't even know how to read the chars and add it to the string, Is there any proper way to do this?
Here's a version that (ab)uses __iter__'s lesser-known "sentinel" argument:
with open('file.txt', 'rb') as f:
val = ''.join(iter(lambda: f.read(1).decode('ascii'), '\x00'))
How about:
myString = myNullTerminatedString.split("\x00")[0]
For example:
myNullTerminatedString = "hello world\x00\x00\x00\x00\x00\x00"
myString = myNullTerminatedString.split("\x00")[0]
print(myString) # "hello world"
This works by splitting the string on the null character. Since the string should terminate at the first null character, we simply grab the first item in the list after splitting. split will return a list of one item if the delimiter doesn't exist, so it still works even if there's no null terminator at all.
It also will work with byte strings:
myByteString = b'hello world\x00'
myStr = myByteString.split(b'\x00')[0].decode('ascii') # "hello world" as normal string
If you're reading from a file, you can do a relatively larger read - estimate how much you'll need to read to find your null string. This is a lot faster than reading byte-by-byte. For example:
resultingStr = ''
while True:
buf = f.read(512)
resultingStr += buf
if len(buf)==0: break
if (b"\x00" in resultingStr):
extraBytes = resultingStr.index(b"\x00")
resultingStr = resultingStr.split(b"\x00")[0]
break
# now "resultingStr" contains the string
f.seek(0 - extraBytes,1) # seek backwards by the number of bytes, now the pointer will be on the null byte in the file
# or f.seek(1 - extraBytes,1) to skip the null byte in the file
(edit version 2, added extra way at the end)
Maybe there are some libraries out there that can help you with this, but as I don't know about them lets attack the problem at hand with what we know.
In python 2 bytes and string are basically the same thing, that change in python 3 where string is what in py2 is unicode and bytes is its own separate type, which mean that you don't need to define a read char if you are in py2 as no extra work is required, so I don't think you need that unpack function for this particular case, with that in mind lets define the new readString
def readString(myfile):
chars = []
while True:
c = myfile.read(1)
if c == chr(0):
return "".join(chars)
chars.append(c)
just like with your code I read a character one at the time but I instead save them in a list, the reason is that string are immutable so doing str+=char result in unnecessary copies; and when I find the null character return the join string. And chr is the inverse of ord, it will give you the character given its ascii value. This will exclude the null character, if its needed just move the appending...
Now lets test it with your sample file
for instance lets try to read "Sword_Wea_Dummy" from it
with open("sword.blendscn","rb") as archi:
#lets simulate that some prior processing was made by
#moving the pointer of the file
archi.seek(6)
string=readString(archi)
print "string repr:", repr(string)
print "string:", string
print ""
#and the rest of the file is there waiting to be processed
print "rest of the file: ", repr(archi.read())
and this is the output
string repr: 'Sword_Wea_Dummy'
string: Sword_Wea_Dummy
rest of the file: '\xcd\xcc\xcc=p=\x8a4:\xa66\xbfJ\x15\xc6=\x00\x00\x00\x00\xeaQ8?\x9e\x8d\x874$-i\xb3\x00\x00\x00\x00\x9b\xc6\xaa2K\x15\xc6=;\xa66?\x00\x00\x00\x00\xb8\x88\xbf#\x0e\xf3\xb1#ITuB\x00\x00\x80?\xcd\xcc\xcc=\x00\x00\x00\x00\xcd\xccL>'
other tests
>>> with open("sword.blendscn","rb") as archi:
print readString(archi)
print readString(archi)
print readString(archi)
sword
Sword_Wea_Dummy
ÍÌÌ=p=Š4:¦6¿JÆ=
>>> with open("sword.blendscn","rb") as archi:
print repr(readString(archi))
print repr(readString(archi))
print repr(readString(archi))
'sword'
'Sword_Wea_Dummy'
'\xcd\xcc\xcc=p=\x8a4:\xa66\xbfJ\x15\xc6='
>>>
Now that I think about it, you mention that the data portion is of fixed size, if that is true for all files and the structure on all of them is as follow
[unknow size data][know size data]
then that is a pattern we can exploit, we only need to know the size of the file and we can get both part smoothly as follow
import os
def getDataPair(filename,knowSize):
size = os.path.getsize(filename)
with open(filename, "rb") as archi:
unknown = archi.read(size-knowSize)
know = archi.read()
return unknown, know
and by knowing the size of the data portion, its use is simple (which I get by playing with the prior example)
>>> strins_data, data = getDataPair("sword.blendscn", 80)
>>> string_data, data = getDataPair("sword.blendscn", 80)
>>> string_data
'sword\x00Sword_Wea_Dummy\x00'
>>> data
'\xcd\xcc\xcc=p=\x8a4:\xa66\xbfJ\x15\xc6=\x00\x00\x00\x00\xeaQ8?\x9e\x8d\x874$-i\xb3\x00\x00\x00\x00\x9b\xc6\xaa2K\x15\xc6=;\xa66?\x00\x00\x00\x00\xb8\x88\xbf#\x0e\xf3\xb1#ITuB\x00\x00\x80?\xcd\xcc\xcc=\x00\x00\x00\x00\xcd\xccL>'
>>> string_data.split(chr(0))
['sword', 'Sword_Wea_Dummy', '']
>>>
Now to get each string a simple split will suffice and you can pass the rest of the file contained in data to the appropriated function to be processed
Doing file I/O one character at a time is horribly slow.
Instead use readline0, now on pypi: https://pypi.org/project/readline0/ . Or something like it.
In 3.x, there's a "newline" argument to open, but it doesn't appear to be as flexible as readline0.
Here is my implementation:
import struct
def read_null_str(f):
r_str = ""
while 1:
back_offset = f.tell()
try:
r_char = struct.unpack("c", f.read(1))[0].decode("utf8")
except:
f.seek(back_offset)
temp_char = struct.unpack("<H", f.read(2))[0]
r_char = chr(temp_char)
if ord(r_char) == 0:
return r_str
else:
r_str += r_char
Im trying to create a finite state machine that reads in the states, transitions, and the strings. I am trying to create it without objects. Everything works up till my for loops. However, as soon as the loop begins I get the error message:
line 42, in <module>
for I in len (Strings):
TypeError: 'int' object is not iterable
Why is this happening? Any tips would be appreciated.
Sfile = open("states.txt","r")
States = []
ReadLine = Sfile.readline()
while ReadLine != "":
A, B, C = ReadLine.split(",")
States.append((A, bool(int(B)), bool(int(C))))
ReadLine = Sfile.readline()
print States, "\n"
Sfile.close()
Tfile = open("transistions.txt","r")
Transitions = []
ReadLine = Tfile.readline()
while ReadLine != "":
ReadLine = ReadLine.rstrip()
Tran4, Tran5, Tran6 = ReadLine.split(",")
Transitions.append((Tran4, Tran5, Tran6))
ReadLine = Tfile.readline()
print Transitions
Tfile.close()
Strfile = open("strings2.txt","r")
Strings = []
ReadLine = Strfile.readline()
while ReadLine != "":
Readline = ReadLine.rstrip()
Strings.append(Readline)
ReadLine = Strfile.readline()
print Strings, '\n'
Strfile.close()
for I in len (Strings):
for C in Strings[I]:
Start = '0'
Current = Start
if C in Strings == '0':
Current = A
else:
Current = State
print Current...
My different text files contain:
states.txt
State2,1,0
State3,0,1
State4,1,0
transitions.txt
State1,0,State2
State2,1,State3
State3,0,State4
strings2.txt
10100101
1001
10010
You can't iterate over an integer. I think you meant to iterate over a range object range(len(Strings)). This will work because the range object is an iterable and the int is not.
You want i in range(len(Strings)). Len returns a whole number, like 13 -- in wants something like a vector. range(13) gives you a vector [0,1,2,3,4,5,6,7,8,9,10,11,12].
Quiz question: why is the last number 12?
You're trying to iterate over an integer, it should be
for I in range(len(Strings))
You will need to turn the number to a string as you cant pick out the first digit of an int. So str(1234)='1234' '1234'[0]='1'
len(s) gives you an integer, and you can't iterate over that. If you want to iterate over a collection of strings, use for s in strings.
you can't iterate over a number or any other singular object, you need a composite object like a list, to do that. In this case look like you want this
for words in Strings:
for C in words:
...