use raw_input generated string safely (Python) - python

I'm wondering how to use a string from raw_input safely so that I can create a function to replace it for a script that is meant to be used easily and securely.
The reason is that I am trying to make a character sheet generating application using python and need to be able to get a character's full name to pass as a string using a name for easy access (Charname_NLB)
However, as I'm looking to use this for more than that application, I need this to be usable for any string entered as raw input, using this alternate command.
I already have a similar piece made for input of integers and would like to integrate it into the same class, for simplicity's sake. I'll post it here, with thanks to: Mgilson and BlueKitties (from here and www.python-forum.org respectively)
def safeinput(get_num):
num = float(raw_input(get_num))
return num
However if this would not return the same result as the base Input command safely, could I please get an working copy, as I currently have only one proof of concept to work with, and it wouldn't be accurate with truncated numbers.
**Edit: By "Any string", I mean specifically that the result will be stored as a string, not used as a command.

Not sure if this is what you are asking for. literal_eval is safe, but only works for literals. It's very difficult to use eval() safely if you have to sanitise the input
>>> from ast import literal_eval
>>> def safeinput(s):
... try:
... return literal_eval(s)
... except:
... return s
...
>>> repr(safeinput("1"))
'1' # converted to an int
>>> repr(safeinput("1.1"))
'1.1' # converted to a float
>>> repr(safeinput("'some string in quotes'"))
"'some string in quotes'" # converted to a string
>>> repr(safeinput("some string without quotes"))
"'some string without quotes'" # no conversion necessary

Related

How to check for a string's "natural" datatype in Python?

I have a user inputting arguments to the command line when running a python3 script, and I wish to check whether specific arguments are floats, ints, booleans, or strings. I'm familiar with the errors that are thrown when a string like 'car' is cast to an int using the int() function, and am also familiar with using a try/except block to attempt to cast a string to an int, and if this is unsuccessful, how to map error messages to helpful output to the user. I've also seen this previous question, which will probably do the job. Was just wondering if there had been any new development.
Not sure if this is possible, but looking for a smart type() function that could operate as such:
#!/usr/bin/env python3
import sys
smarttype(sys.argv[-1])
and is capable of handling the following kinds of inputs:
./script.py 50
./script.py True
./script.py 50.0
./script.py run
and output:
int
bool
float
str
I usually use ast.literal_eval to parse “elementary” data types:
type(ast.literal_eval('50')) # outputs int
You need however a set of quotes to mark something as a string (otherwise every input could be taken as a string):
type(ast.literal_eval('run')) # error
type(ast.literal_eval('"run"')) # string
If you want to allow unqouted strings you could do the following:
def parse_data(x):
"""Takes a string x and returns the "value" of x"""
try:
return ast.literal_eval(x)
except (ValueError, SyntaxError):
return x

How to return a string without quotes Python 3

I've got to write a single-input module that can convert decimals to Bukiyip (some ancient language with a counting base of 3 or 4). For the purpose of the assignment, we only need to work with base 3.
I've written some code that does this, but it returns my Bukiyip number with quotes, leaving me with an answer such as '110' for 12.
Please help me understand how to work around this? I'm new to Python and keen to learn so explanations will be really appreciated.
def bukiyip_to_decimal(num):
convert_to_string = "012"
if num < 3:
return convert_to_string[num]
else:
return bukiyip_to_decimal(num//3) + convert_to_string[num%3]
I've also tried the following, but get errors.
else:
result = bukiyip_to_decimal(num//3) + convert_to_string[num%3]
print(int(result))
You are either echoing the return value in your interpreter, including the result in a container (such as a list, dictionary, set or tuple), or directly producing the repr() output for your result.
Your function (rightly) returns a string. When echoing in the interpreter or using the repr() function you are given a debugging-friendly representation, which for strings means Python will format the value in a way you can copy and paste right back into Python to reproduce the value. That means that the quotes are included.
Just print the value itself:
>>> result = bukiyip_to_decimal(12)
>>> result
'110'
>>> print(result)
110
or use it in other output:
>>> print('The Bukiyip representation for 12 is {}'.format(result))
The Bukiyip representation for 12 is 110
int() doesn't work? The quotes are not for decoration, you see. They are part of the string literal representation. "hello" is a string. It is not hello with quotes. A bare hello is an identifier, a name. So you don't wanna strip quotes from a string, which doesn't make any sense. What you want is a int.

python replace string method in read file as binary

I opened an image file in readbinary("rb") mode and stored the data in a variable. Now i want to replace some values in the binary with my values.. but its not working using usual replace method of string
f=open("a.jpg","rb")
a=f.read()
''' first line is '\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xe1\x00*Exif\x00\x00II*\x00\x08\x00\x00\x00\x0 '''
a=a.replace("ff","z")
print a
#but there's no change in a
can anyone tell where iam going wrong.. i also tried
a=a.replace(b'ff',b'z')
but still the output was unchanged.
can anyone tell what iam supposed to do to perform the replacement?
I don't know which version of Python you're using (this kind of operations are different between 2 and 3), but try a = str(a) before executing replace method.
EDIT: For python 2.7 only reasonable way I've discovered to do what you want is use built-in function repr. Example:
>>> picture = open("some_picture.jpg", 'rb')
>>> first_line = picture.readline()
>>> first_line
'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xe1\x00*Exif\x00\x00II*\x00\x08\x00\x00\x00\x01\x001\x01\x02\x00\x07\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x00\x00Google\x00\x00\xff\xdb\x00\x84\x00\x03\x02\x02\x03\x02\x02\x03\x03\x03\x03\x04\x03\x03\x04\x05\x08\x05\x05\x04\x04\x05\n'
>>> repr(first_line)
>>> "'\\xff\\xd8\\xff\\xe0\\x00\\x10JFIF\\x00\\x01\\x01\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\xff\\xe1\\x00*Exif\\x00\\x00II*\\x00\\x08\\x00\\x00\\x00\\x01\\x001\\x01\\x02\\x00\\x07\\x00\\x00\\x00\\x1a\\x00\\x00\\x00\\x00\\x00\\x00\\x00Google\\x00\\x00\\xff\\xdb\\x00\\x84\\x00\\x03\\x02\\x02\\x03\\x02\\x02\\x03\\x03\\x03\\x03\\x04\\x03\\x03\\x04\\x05\\x08\\x05\\x05\\x04\\x04\\x05\\n'"
>>> repr(first_line).replace('ff', 'SOME_OTHER_STRING')
"'\\xSOME_OTHER_STRING\\xd8\\xSOME_OTHER_STRING\\xe0\\x00\\x10JFIF\\x00\\x01\\x01\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\xSOME_OTHER_STRING\\xe1\\x00*Exif\\x00\\x00II*\\x00\\x08\\x00\\x00\\x00\\x01\\x001\\x01\\x02\\x00\\x07\\x00\\x00\\x00\\x1a\\x00\\x00\\x00\\x00\\x00\\x00\\x00Google\\x00\\x00\\xSOME_OTHER_STRING\\xdb\\x00\\x84\\x00\\x03\\x02\\x02\\x03\\x02\\x02\\x03\\x03\\x03\\x03\\x04\\x03\\x03\\x04\\x05\\x08\\x05\\x05\\x04\\x04\\x05\\n'"
When you display a string at the Python console, the string is encoded so that you can see all of the characters, even the ones that aren't printable. Whenever you see something like \xff, that's not 4 characters, it's a single character in hex notation. To replace it, you also need to specify the same single character.
a = a.replace("\xff", "z")

Python, Need Long Value to be Integer

I'm trying to insert a unix timestamp using REST to a webservice. And when I convert the dictionary I get the value: 1392249600000L I need this value to be an integer.
So I tried int(1392249600000L) and I get 1392249600000L, still a long value.
The reason I need this is because the JSON webservice only accepts timestamsp with milliseconds in them, but when I pass the JSON value with the 'L' in it I get an invalid JSON Primative of value 1392249600000L error.
Can someone please help me resolve this? It seems like it should be so easy, but it's driving me crazy!
You should not be using Python representations when you are sending JSON data. Use the json module to represent integers instead:
>>> import json
>>> json.dumps(1392249600000L)
'1392249600000'
In any case, the L is only part of the string representation to make debugging easier, making it clear you have a long, not int value. Don't use Python string representations for network communications, in any case.
For example, if you have a list of Python values, the str() representation of that list will also use repr() representations of the contents of the list, resulting in L postfixes for long integers. But json.dumps() handles such cases properly too, and handle other types correctly too (like Python None to JSON null, Python True to JSON true, etc.):
>>> json.dumps([1392249600000L, True, None])
'[1392249600000, true, null]'

How does the following code snippet work?

I am a novice in python and am going through an opensource project called pyOBD by Donour Sizemore for the ELM327(not really sure,could be aimed at more scantool devices).I can make out that the following is a method to convert a hex value to int.But how does it work? Specially the line with eval in it.
def hex_to_int(str):
i = eval("0x" + str, {}, {})
return i
eval runs a string as if it were Python code, and then outputs the result.
In this case, it runs something like 0xaf, which is a way of specifying a hexadecimal literal, and outputs the resulting integer. Try typing 0xaf into the Python interpreter, and you'll get an integer as the result.
eval is not safe to use on untrusted input. For example,
eval("0xa and __import__('os').remove('some/file/path')")
could delete a file on your system.
It would be better to use ast.literal_eval or int:
>>> import ast
>>> ast.literal_eval("0xaf")
175
>>> int("af", 16)
175
Which are safe and produce the same result.

Categories