'str' does not support the buffer interface Python3 from Python2 - python

Hi have this two funtions in Py2 works fine but it doesn´t works on Py3
def encoding(text, codes):
binary = ''
f = open('bytes.bin', 'wb')
for c in text:
binary += codes[c]
f.write('%s' % binary)
print('Text in binary:', binary)
f.close()
return len(binary)
def decoding(codes, large):
f = file('bytes.bin', 'rb')
bits = f.read(large)
tmp = ''
decode_text = ''
for bit in bits:
tmp += bit
if tmp in fordecodes:
decode_text += fordecodes[tmp]
tmp = ''
f.close()
return decode_text
The console ouputs this:
Traceback (most recent call last):
File "Practica2.py", line 83, in <module>
large = encoding(text, codes)
File "Practica2.py", line 56, in encoding
f.write('%s' % binary)
TypeError: 'str' does not support the buffer interface

The fix was simple for me
Use
f = open('bytes.bin', 'w')
instead of
f = open('bytes.bin', 'wb')
In python 3 'w' is what you need, not 'wb'.

In Python 2, bare literal strings (e.g. 'string') are bytes, whereas in Python 3 they are unicode. This means if you want literal strings to be treated as bytes in Python 3, you always have to explicitly mark them as such.
So, for instance, the first few lines of the encoding function should look like this:
binary = b''
f = open('bytes.bin', 'wb')
for c in text:
binary += codes[c]
f.write(b'%s' % binary)
and there are a few lines in the other function which need similar treatment.
See Porting to Python 3, and the section Bytes, Strings and Unicode for more details.

Related

Python binary messes up some files

I have written two python scripts. One of which encodes the file to binary, stores it as a textfile for later decryption. The other script can turn the textfile back into readable information, or at least, that's my aim.
script 1 (encrypt)
(use any .png image file as input, any .txt file as output):
u_input = input("What file to encrypt?")
file_store = input("Where do you want to store the binary?")
character = "" #Blank for now
encrypted = "" #Blank for now, stores the bytes before they are written
with open(u_input, 'rb') as f:
while True:
c = f.read(1)
if not c:
f.close()
break
encrypted = encrypted + str(bin(ord(c))[2:].zfill(8))
print("")
print(encrypted) # This line is not necessary, but I have included it to show that the encryption works
print("")
with open(file_store, 'wb') as f:
f.write(bytes(encrypted, 'UTF-8'))
f.close()
As far as I can tell, this works okay for text files (.txt)
I then have a second script (to decrypt the file)
Use the previously created .txt file as source, any .png file as dest:
u_input =("Sourcefile:")
file_store = input("Decrypted output:")
character = ""
decoded_string = ""
with open(u_input, 'r' as f:
while True:
c = f.read(1)
if not c:
f.close()
break
character = character + c
if len(character) % 8 == 0:
decoded_string = decoded_string + chr(int(character, 2))
character = ""
with open(file_store, 'wb') as f:
f.write(bytes(decoded_string, 'UTF-8'))
f.close()
print("SUCCESS!")
Which works partially. i.e. it writes the file. However, I cannot open it or edit it. When I compare my original file (img.png) with my second file (img2.png), I see characters have been replaced or line breaks not entered correctly. I can't view the file in any image viewing / editing program. I do not understand why.
Please could someone try to explain and provide a solution (albeit, partial)? Thanks in advance.
Note: I am aware that my use of "encryption" and "decryption" are not necessarily used correctly, but this is a personal project, so it doesn't matter to me
It appears you're using Python 3, as you put a UTF-8 parameter on the bytes call. That's your problem - the input should be decoded to a byte string, but you're putting together a Unicode string instead, and the conversion isn't 1:1. It's easy to fix.
decoded_string = b""
# ...
decoded_string = decoded_string + bytes([int(character, 2)])
# ...
f.write(decoded_string)
For a version that works in both Python 2 and Python 3, another small modification. This actually measures faster for me in Python 3.5 so it should be the preferred method.
import struct
# ...
decoded_string = decoded_string + struct.pack('B', int(character, 2))

Error writing output file 'int' does not support the buffer interface

I an new to Python, trying to overwrite the last 128 bytes of a file with zer0s. What am I doing wrong?
try:
f = open(outputFile, "wb")
for x in range(1, 128):
f.seek(x, 2) # seek relative to end of file
f.write(0)
f.close()
except Exception as e:
sys.exit('Error writing output file ' + str(e))
Error writing output file 'int' does not support the buffer interface
[Update]
this runs with no error, but the zer0s are not written (I mean \0 (end of string))
f = open(outputFile, "rb+")
zeros = bytearray(0 * 128)
f.seek(-128, 2) # seek relative to end of file
f.write(zeros)
f.close()
Note: when I tried f.write('\0'*128) I got Error writing output file 'str' does not support the buffer interface
If you mean NUL bytes
f.write('\0')
If you want actual zeros
f.write('0')
If you mean to overwrite just the last part of the file (as opposed to append)
with open('x', 'rb+') as f:
f.seek(-128, 2)
f.write('\0'*128)
replace this:
f.write(0)
to:
f.write(str(0))
you need to convert it to type str

startswith TypeError in function

Here is the code:
def readFasta(filename):
""" Reads a sequence in Fasta format """
fp = open(filename, 'rb')
header = ""
seq = ""
while True:
line = fp.readline()
if (line == ""):
break
if (line.startswith('>')):
header = line[1:].strip()
else:
seq = fp.read().replace('\n','')
seq = seq.replace('\r','') # for windows
break
fp.close()
return (header, seq)
FASTAsequence = readFasta("MusChr01.fa")
The error I'm getting is:
TypeError: startswith first arg must be bytes or a tuple of bytes, not str
But the first argument to startswith is supposed to be a string according to the docs... so what is going on?
I'm assuming I'm using at least Python 3 since I'm using the latest version of LiClipse.
It's because you're opening the file in bytes mode, and so you're calling bytes.startswith() and not str.startswith().
You need to do line.startswith(b'>'), which will make '>' a bytes literal.
If remaining to open a file in binary, replacing 'STR' to bytes('STR'.encode('utf-8')) works for me.
Without having your file to test on try encoding to utf-8 on the 'open'
fp = open(filename, 'r', encoding='utf-8')

Write a "string" as raw binary into a file Python

I'm trying to write a series of files for testing that I am building from scratch. The output of the data payload builder is of type string, and I'm struggling to get the string written directly to the file.
The payload builder only uses hex values, and simply adds a byte for each iteration.
The 'write' functions I have tried all either fall over the writing of strings, or write the ASCII code for the string, rather than the string its self...
I want to end up with a series of files - with the same filename as the data payload (e.g. file ff.txt contains the byte 0xff
def doMakeData(counter):
dataPayload = "%X" %counter
if len(dataPayload)%2==1:
dataPayload = str('0') + str(dataPayload)
fileName = path+str(dataPayload)+".txt"
return dataPayload, fileName
def doFilenameMaker(counter):
counter += 1
return counter
def saveFile(dataPayload, fileName):
# with open(fileName, "w") as text_file:
# text_file.write("%s"%dataPayload) #this just writes the ASCII for the string
f = file(fileName, 'wb')
dataPayload.write(f) #this also writes the ASCII for the string
f.close()
return
if __name__ == "__main__":
path = "C:\Users\me\Desktop\output\\"
counter = 0
iterator = 100
while counter < iterator:
counter = doFilenameMaker(counter)
dataPayload, fileName = doMakeData(counter)
print type(dataPayload)
saveFile(dataPayload, fileName)
To write just a byte, use chr(n) to get a byte containing integer n.
Your code can be simplified to:
import os
path = r'C:\Users\me\Desktop\output'
for counter in xrange(100):
with open(os.path.join(path,'{:02x}.txt'.format(counter)),'wb') as f:
f.write(chr(counter))
Note use of raw string for the path. If you had a '\r' or '\n' in the string they would be treated as a carriage return or linefeed without using a raw string.
f.write is the method to write to a file. chr(counter) generates the byte. Make sure to write in binary mode 'wb' as well.
dataPayload.write(f) # this fails "AttributeError: 'str' object has no attribute 'write'
Of course it does. You don't write to strings; you write to files:
f.write(dataPayload)
That is to say, write() is a method of file objects, not a method of string objects.
You got this right in the commented-out code just above it; not sure why you switched it around here...

Why is Python giving me "an integer is required" when it shouldn't be?

I have a save function within my Python program which looks like this:
def Save(n):
print("S3")
global BF
global WF
global PBList
global PWList
print(n)
File = open("C:\KingsCapture\Saves\\" + n + "\BF.txt", "w")
pickle.dump(BF, File)
File = open("C:\KingsCapture\Saves\\" + n + "\WF.txt", "w")
pickle.dump(WF, File)
File = open("C:\KingsCapture\Saves\\" + n + "\PBList.txt", "w")
pickle.dump(PBList, File)
File = open("C:\KingsCapture\Saves\\" + n + "\PWList.txt", "w")
pickle.dump(PWList, File)
Here, n is "1".
I get an error looking like this:
File "C:/Python27/KingsCapture.py", line 519, in Save
File = open("C:\KingsCapture\Saves\\" + n + "\BF.txt", "w")
TypeError: an integer is required
Upon doing the same loading within the shell, I get no errors:
>>> File = open("C:\KingsCapture\Test\List.txt", "r")
>>> File = open("C:\KingsCapture\Test\List.txt", "w")
>>> n = "1"
>>> File = open("C:\KingsCapture\Saves\\" + n + "\BF.txt", "r")
>>> File = open("C:\KingsCapture\Saves\\" + n + "\BF.txt", "w")
Why is this having a problem?
You probably did a star import from the os module:
>>> open("test.dat","w")
<open file 'test.dat', mode 'w' at 0x1004b20c0>
>>> from os import *
>>> open("test.dat","w")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: an integer is required
so you're using the wrong open function. (I suppose you could've simply done from os import open, but that's less likely.) In general this import style should be avoided, as should use of global, where practical.
You need to escape your strings: a \ in a string is an escape character.
Either escape the slashes:
"C:\\KingsCapture\\Test\\List.txt"
or use Raw strings:
r"C:\KingsCapture\Test\List.txt"
As DSM noted, you're using http://docs.python.org/library/os.html#os.open instead of built-in open() function.
In os.open() the second parameter (mode) should be integer instead of string. So, if you ought to use from os import * then just substitute mode string with one of the following args:
os.O_RDONLY
os.O_WRONLY
os.O_RDWR
os.O_APPEND
os.O_CREAT
os.O_EXCL
os.O_TRUNC
I'll bet that n is 1 not "1".
try:
print(type(n))
I'll guess that you'll see its an int not a string.
File = open("C:\KingsCapture\Saves\\" + n + "\BF.txt", "w")
You can't add ints and strings producing the error message you are getting.

Categories

Resources