Converting a string-like object into a string in python - python

I am using python and XMLBuilder, a module I downloaded off the internet (pypi). It returns an object, that works like a string (I can do print(x)) but when I use file.write(x) it crashes and throws an error in the XMLBuilder module.
I am just wondering how I can convert the object it returns into a string?
I have confirmed that I am writing to the file correctly.
I have already tried for example x = y although, as I thought, it just creates a pointer, and also x=x+" " put I still get an error. It also returns an string like object with "\n".
Any help on the matter would be greatly appreciated.

file.write(str(x))
will likely work for you.
Background information: Most types have a function __str__ or __repr__ (or both) defined. If you pass an object of such a type to print, it'll recognize that you did not pass a str and try to call one of these functions in order to convert the object to a string.
However, not all functions are as smart as print and will fail if you pass them something that is not a string. Also string concatenation does not work with mixed types. To work with these functions you'll have to convert the non-string-type objects manually, by wrapping them with str(). So for example:
x = str(x)+" "
This will create a new string and assign it to the variable x, which held the object before (you lose that object now!).

The Library has __str__ defined:
def __str__(self):
return tostring(~self, self.__document()['encoding'])
So you just need to use str(x):
file.write(str(x))

I'm not quite sure what your question is, but print automatically calls str on all of it's arguments ... So if you want the same output as print to be put into your file, then myfile.write(str(whatever)) will put the same text in myfile that print (x) would have put into the file (minus a trailing newline that print puts in there).

When you write:
print myObject
The __repr__ method is actually called.
So for example you could do: x += myXMLObject.__repr__() if you want to append the string representation of that object to your x variable.

Related

Python 3.6+, change representation of None in file

I have to extract from several sources and save the result to csv files. When the data received for a field is None, I want it represented as empty string. (I realize I'll lose the distinction between empty string and NULL-type values in the source.)
My underlying requirement is to preserve the distinction between the string "None" and nothingness in a plain delimited file, without using quotes.
I hope to avoid calling a function that checks if a value is null for every nullable field I write, or at least have that call not explicit in the code... e.g., I want to just code f.write(row['LastName'], and if the LastName is "None" get "None", but if it is of NoneType get an empty string.
I haven't yet investigated if the comes-with csv library can do what I need, I will do that, it seems likely that's the easiest approach.
But: is there anything I can override, so that if I write None to a file, I get empty string (or something besides the string "None" in the output file?
It seems to me I'd have to change either 1) the built-in write method of _io.TextIOWrapper or 2) the __str__ method of the NoneType.
if row['LastName'] is None will check if your value is a NoneType
Something like:
if row['LastName'] is None:
f.write("")
else:
f.write(row['LastName'])
Would get the job done.

Behavior of python's repr method

I understand that the goal of repr is to be unambiguous, but the behavior of repr really confused me.
repr('"1"')
Out[84]: '\'"1"\''
repr("'1'")
Out[85]: '"\'1\'"'
Based on the above code, I think repr just put '' around the string.
But when i try this:
repr('1')
Out[82]: "'1'"
repr("1")
Out[83]: "'1'"
repr put "" around strings and repr("1") and repr('1') is the same.
Why?
There are three levels of quotes going on here!
The quotes inside the string you're passing (only present in your first example).
The quotes in the string produced by repr. Keep in mind that repr tries to return a string representation that would work as Python code, so if you pass it a string, it will add quotes around the string.
The quotes added by your Python interpreter upon printing the output. These are probably what confuses you. Probably your interpreter is calling repr again, in order to give you an idea of the type of object being returned. Otherwise, the string 1 and the number 1 would look identical.
To get rid of this extra level of quoting, so you can see the exact string produced by repr, use print(repr(...)) instead.
The python REPL (and Ipython in your case) print out the repr() of the output value, so your input is getting repred twice.
To avoid this, print it out instead.
>>> repr('1') # what you're doing
"'1'"
>>> print(repr('1')) # if you print it out
'1'
>>> print(repr(repr('1'))) # what really happens in the first line
"'1'"
The original (outer) quotes may not be preserved since the object being repred has no idea what they originally were.
From documentation:
repr(object): Return a string containing a printable representation of
an object.
So it returns a string that given to Python can be used to recreate that object.
Your first example:
repr('"1"') # string <"1"> passed as an argument
Out[84]: '\'"1"\'' # to create your string you need to type like '"1"'.
# Outer quotes are just interpretator formatting
Your second example:
repr("'1'") # you pass a string <'1'>
Out[85]: '"\'1\'"' # to recreate it you have to type "'1'" or '\'1\'',
# depending on types of quotes you use (<'> and <"> are the same in python
Last,
repr('1') # you pass <1> as a string
Out[82]: "'1'" # to make that string in python you type '1', right?
repr("1") # you pass the same <1> as string
Out[83]: "'1'" # to recreate it you can type either '1' or "1", does not matter. Hence the output.
I both interpreter and repr set surrounding quotes to ' or " depending on content to minimize escaping, so that's why output differs.

Iterable error with int when using for / argument ()error while using map. Where am i going worng

I tried bith ways using map nad using for loop but its not working i know for for loop it has to list,tuples or string. So how do i make this work
1
def narcissistic(value):
x = ((value)== sum((c)**len(value) for c in list(value)))
return x
2
def narcissistic(value):
x=(value== (map(lambda c :sum(c**len(value)),value)))
return x
Your issue comes down to confusion about the type of your different objects. Python is a strongly typed language, so each object has a clear type at any given moment and the language generally won't convert anything to another type automatically for you.
Based on the error you're getting, you're calling your function with an int argument. This causes you trouble when you try to call len or iterate on your value. Python ints don't have a length, nor are they iterable, so it's quite understandable that these fail under the circumstances.
What you want to do is create a string representation of your value number. Then you can loop over the characters of the string, and take its len freely.
There's another issue though. You're also trying to do an exponential operation on the c variable in the generator expression. That won't work because c is a string, not a number. It's a one-digit string, but still a str instance! To do math with it, you need to convert it back to a number with int.
Here's a fixed version of your function:
def narcissistic(number):
num_str = str(number)
return sum(int(c)**len(num_str) for c in num_str) == number
I've renamed the very generic value name with number, which should hopefully make it more clear what type each thing is.

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")

use raw_input generated string safely (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

Categories