Is this a safe way to use eval() in python? - python-3.x

I understand that running eval on user input is very dangerous, does limiting the input like I've done in the code below eliminate all the danger?
q=''
safe=['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '+', '-', '*', '/', '(', ')', '.']
while True:
i= input('input = ')
if i == 'exit':
exit('Shutting Down.')
elif i in safe:
q += i
elif i == '=':
print(eval(q))
else:
print('no')
If this still contains vulnerabilities, is there some way to add the symbols to a string of numbers and calculate the answer? I know I can simply use float() for converting the string numbers to actual numbers but I have no idea how I could add '+' as just a + so it can be used in a calculation.
Edit: Switched the code since I accidentally uploaded the wrong code

If you want to check the entire input string, you can put the safe characters in a set then compare the input to the safe set.
Try this code:
safe=['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '+', '-', '*', '/', '(', ')', '.']
safeall = set(safe) # all safe characters
while True:
i= input('input = ').strip()
if i == 'exit':
exit('Shutting Down.')
if safeall & set(i) == set(i): # if input in safe characters
print('Safe')
print(eval(i))
else:
print('Not Safe')
Output
input = test123
Not safe
input = ##$$%%
Not safe
input = 12 + 67
Safe
79
input = exit
Shutting Down.

Related

How to iterate a list, to get combination of all next values

Problem: Obtain the combination of all next values of the array.
Explanation: All the values should be formed by contiguous elements in the array.
Posible solution(not optimal):
l_number= list("24256")
result= []
while l_number:
n = ""
for x in l_number:
n += x
result.append(str(n))
l_number.pop(0)
print(result)
The output:
['2', '24', '242', '2425', '24256', '4', '42', '425', '4256', '2', '25', '256', '5', '56', '6']
I got this, but it is not very efficient.
Is there any optimized way to do this?
Since you will be outputting all contiguous sublists, the size of the output will be O(N^2) where N is the length of the list, and time complexity will be at least quadratic no matter what (You could achieve linear space complexity by using a generator). Here is one way to compute all contiguous substrings with a list comprehension:
s = "24256"
n = len(s)
res = [s[i:j] for i in range(n) for j in range(i+1,n+1)]
print(res)
# ['2', '24', '242', '2425', '24256', '4', '42', '425', '4256', '2', '25', '256', '5', '56', '6']
As an aside, it is usually undesirable to build up lists with str += ... since a new copy of str is created on each iteration. One workaround is to create a list of components and call .join once all components have been found.

How to determine "event" output to print on the outcome of a random dice roll?

I'm trying to have certain strings print out depending on which dice roll is made.
I have tried making lists for what rolls get which event, but even at that no event prints out only what i have rolled.
import random
def dice_roll():
d20_roll = random.randint(1,20)
print("You rolled " +str(d20_roll))
def dice_choice():
event = str(d20_roll)
bad_list = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
'11', '12']
good_list = ['13', '14', '15', '16', '17', '18']
gag_list = ['19', '20']
if event == bad_list:
print('bad_list stuff')
elif event == good_list:
print('good_list stuff')
else:
if event == print gag_list:
print("gag_list stuff")
dice_choice()
dice_roll()
I expect the output to be any of the three options the random roll will make.
What I receive is just the result of the dice_roll itself, without the choice.
First, check your indentation, your call to dice_choice() seems to be inside dice_choice() itself, second, there is a syntax error in your test if event == print gag_list:, third, you are testing whether a string equals a list, instead you should test whether the string is in the list, your code should be like this:
import random
def dice_roll():
d20_roll = random.randint(1,20)
print("You rolled " +str(d20_roll))
def dice_choice():
event = str(d20_roll)
bad_list = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']
good_list = ['13', '14', '15', '16', '17', '18']
gag_list = ['19', '20']
if event in bad_list: # check using `in` not `===`
print('bad_list stuff')
elif event in good_list:
print('good_list stuff')
elif event == gag_list:
print("gag_list stuff")
dice_choice()
dice_roll()
Example Output:
You rolled 11
bad_list stuff

Concat multiple CSV rows into 1 in python

I am trying to contact the CSV rows. I tried to convert the CSV rows to list by pandas but it gets 'nan' values appended as some files are empty.
Also, I tried using zip but it concats column values.
with open(i) as f:
lines = f.readlines()
res = ""
for i, j in zip(lines[0].strip().split(','), lines[1].strip().split(',')):
res += "{} {},".format(i, j)
print(res.rstrip(','))
for line in lines[2:]:
print(line)
I have data as below,
Input data:-
Input CSV Data
Expected Output:-
Output CSV Data
The number of rows are more than 3,only sample is given here.
Suggest a way which will achieve the above task without creating a new file. Please point to any specific function or sample code.
This assumes your first line contains the correct amount of columns. It will read the whole file, ignore empty data ( ",,,,,," ) and accumulate enough data points to fill one row, then switch to the next row:
Write test file:
with open ("f.txt","w")as f:
f.write("""Circle,Year,1,2,3,4,5,6,7,8,9,10,11,12
abc,2018,,,,,,,,,,,,
2.2,8.0,6.5,9,88,,,,,,,,,,
55,66,77,88,,,,,,,,,,
5,3.2,7
def,2017,,,,,,,,,,,,
2.2,8.0,6.5,9,88,,,,,,,,,,
55,66,77,88,,,,,,,,,,
5,3.2,7
""")
Process test file:
data = [] # all data
temp = [] # data storage until enough found , then put into data
with open("f.txt","r") as r:
# get header and its lenght
title = r.readline().rstrip().split(",")
lenTitel = len(title)
data.append(title)
# process all remaining lines of the file
for l in r:
t = l.rstrip().split(",") # read one lines data
temp.extend( (x for x in t if x) ) # this eliminates all empty ,, pieces even in between
# if enough data accumulated, put as sublist into data, keep rest
if len (temp) > lenTitel:
data.append( temp[:lenTitel] )
temp = temp [lenTitel:]
if temp:
data.append(temp)
print(data)
Output:
[['Circle', 'Year', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
['abc', '2018', '2.2', '8.0', '6.5', '9', '88', '55', '66', '77', '88', '5', '3.2', '7'],
['def', '2017', '2.2', '8.0', '6.5', '9', '88', '55', '66', '77', '88', '5', '3.2', '7']]
Remarks:
your file cant have leading newlines, else the size of the title is incorrect.
newlines in between do not harm
you cannot have "empty" cells - they get eliminated
As long as nothing weird is going on in the files, something like this should work:
with open(i) as f:
result = []
for line in f:
result += line.strip().split(',')
print(result)

LPTHW 48: nosetest says AttributeError: 'str' object has no attribute ' ' while output seems correct?

I'm working on LPTHW and I'm trying to understand my error.
This is my code:
class lexicon:
def __init__(self, words):
self.words = words
def scan(self):
direction = ['north', 'south', 'east', 'west']
verb = ['go', 'stop', 'kill', 'eat']
stop = ['the', 'in', 'of', 'from', 'at', 'it']
noun = ['door', 'bear', 'princess', 'cabinet']
number = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
thewords = self.words.split()
output = []
for i in thewords:
if i in direction:
output.append(('direction', i ))
print(output)
lexicon('north').scan()
I've put in the print statement to check if the output is correct. The actual output:
[('direction', 'north')]
I'm trying to get my nose test script running with this:
from nose.tools import *
from ex48 import lexicon
def test_directions():
assert_equal(lexicon.scan("north"), [('direction', 'north')])
But when I execute it:
thewords = self.words.split()
AttributeError: 'str' object has no attribute 'words'
The output of the script seems to match what the nose script expects, a tupil with those values. But the error seems to say that I gave it a string and it wants something else? I've searched on the error message but I can't wrap my head around what it's trying to tell me here.
Can somebody explain what I'm doing wrong here?

Why may this construction be not working?

I receive, that first iteration 1 is not a number.
numbers = ['1', 'apple', '2', '3', '4', '5']
print ('Your numbers are...')
for f in numbers:
if f.isalpha():
print ('This is not a number!') # (It actually isn't.)
break
print (f)
else:
print ('Here are your numbers!')
You're seeing this...
Your numbers are...
Then you hit the first iteration, f = '1' and print (f):
1
Then you get to the second iteration, f = 'apple' and print ('This is not a number!')...
This is not a number!
This is to be expected.
Your output would be clearer with this program:
#!/usr/bin/env python3
numbers = ['1', 'apple', '2', '3', '4', '5']
print ('Your numbers are...')
for f in numbers:
if f.isalpha():
print('{} is not a number!'.format(f))
break
else:
print('Here are your numbers: {}'.format(numbers))

Resources