-1

I'm trying to web scraping in python. I'm using python 3.6 and import necessary packages for this. But I encounter an Attribute Error of 'bytes' object has no attribute 'format'. If there is no format method for bytes, how to do the formatting or "rewriting" of bytes

 f = open(b'{0}.jpg'.format(flim.title.encode('utf8').replace(':','')) , 'wb')
 f.write(requests.get(all_img[1]['src']).content)
 f.close()

I was also facing the following problem

a bytes-like object is required, not 'str'

and get rid of it by using 'b' right before the format specifier.

UPDATE 1

I remove the 'b' prefix and also give 'w' mode only and now I get the following error: TypeError: a bytes-like object is required, not 'str'

Error

 TypeError                                 Traceback (most recent call last)
<ipython-input-7-7a0edc6fdfd0> in <module>()
----> 1 download_poster(get_list())

<ipython-input-6-49c729cbcc37> in download_poster(list_)
     30                 #       f.write(requests.get(all_img[1]['src']).content)
     31 
---> 32                 f = open('{0}.jpg'.format(flim.title.encode('utf-8').replace(':','')) , 'w')
     33                 f.write(requests.get(all_img[1]['src']).content)
     34                 f.close()

TypeError: a bytes-like object is required, not 'str'

I was wondering I might make a silly mistake. Excuse me for that. Thanks in advance.

UPDATE 2

I somehow able to fix this by changing some format. Using f-strings(formatted string literals)

with open(f'{flim.title}.jpg', 'wb') as f:
            f.write(requests.get(all_img[1]['src']).content)
Innat
  • 16,113
  • 6
  • 53
  • 101
  • An important part of questions is including a traceback. I think removing the `b` prefix moves the issue elsewhere but you're aggregating it into a single issue. – roganjosh Apr 24 '18 at 17:35
  • Semantically, formatting doesn't make sense for bytes. You want to format a *string*, then (if needed) encode that string as a series of bytes. – chepner Apr 24 '18 at 17:37

2 Answers2

2

The issue is quite trivial.

Preface

Python supports multiple prefixes to the 'someString'

  • r'something' : This is a raw string generally used when you're using file paths for example file_path = r'C:\MyProjects\Python\TestProject'. It tells the interpreter that this is araw stringand no escape sequences (e.g.\n`) have a meaning here.
  • f'something' : This is a string interpolation feature available in python3.5+ allows you to have place holders in the string to set a value. for example,

my_variable = 5 
some_string = f'I have {my_variable} apples with me'
# prints I have 5 apples with me
  • b'something' : This indicates bytes although you type in a string here, since a string is a sequence of bytes, the interpreter understands the prefix b as bytes.

Your issue:

Since you have a b'{0}.jpg' python understands it as bytes and not a string. The .format() is a string function and not a bytes function and hence the error

Attribute Error: 'bytes' object has no attribute 'format'

How to resolve it?

Simple, you can simply remove the prefix b from the b'{0}.jpg' and it'll start to work.

The second issue you've mentioned: Now about the second issue, you've opened the file in wb mode, that stands for write bytes because of which it's expecting bytes as an input to write.

How to resolve it:

Simply, open the file in w mode which would accept strings. I'll add a sample in just a moment.


Your updated code:

f = open('{0}.jpg'.format(flim.title.replace(':','')) , 'w')
f.write(requests.get(all_img[1]['src']).content)
f.close()

Alternatively if you're using python3.5+ I use string interpolation:

f = open(f'{flim.title.replace(':','')}.jpg', 'w')
f.write(requests.get(all_img[1]['src']).content)
f.close()

Also, a better way to do it would be using the with keyword to avoid any Resource Leaks

with open(f'{flim.title.replace(':','')}.jpg', 'w') as f:
    f.write(requests.get(all_img[1]['src']).content)

You don't need to do a f.close() since the with statement would automatically close the file for you.

iam.Carrot
  • 4,976
  • 2
  • 24
  • 71
  • But the issue is pushed elsewhere. The OP, I think, assumes that both errors come entirely from `b'{0}.jpg'` but it's not the case. Removing the`b` prefix fixes the first issue. – roganjosh Apr 24 '18 at 17:38
  • 1
    @roganjosh yeah, see your updated code in my answer, there are two changes, one is the `b` and second is the `w` in `wb` when you're defining the mode in which the file is to be opened. – iam.Carrot Apr 24 '18 at 17:47
  • 1
    @iam.Carrot Thanks for your brief explanation. But unfortunately i still get similar problem. I remove 'b' prefix and also put 'w' in mode and now it shows 'TypeError: a bytes-like object is required, not 'str' '. I have heard about string interpolation in Swift. While i'm using string interpolation here ( what you gave ) it gives syntax error. I'm sorry , i think i'm missing something here. – Innat Apr 24 '18 at 19:17
  • About the string interpolation, as i mentioned, you need to have python 3.5+ maybe you're using a lower version of python that doesn't support string interpolation – iam.Carrot Apr 24 '18 at 19:21
  • About the bytes error, I am not sure why is it still causing the error, can you please update your code after the changes. It'll help clarify a few things. – iam.Carrot Apr 24 '18 at 19:23
  • 1
    @iam.Carrot I update my code , please check it. – Innat Apr 24 '18 at 19:51
  • Hi, thanks for the code. It makes more sense. One last thing. Can you add your stack trace to the question too? – iam.Carrot Apr 25 '18 at 02:41
  • @iPhoton did it start working? – iam.Carrot Apr 25 '18 at 14:13
  • 3
    @iam.Carrot yes , it is and thanks for your information. – Innat Apr 25 '18 at 15:02
1

You have opened file in wb mode, Hence file requires byte not string.

You can do one of the following,

  1. Open file in w mode.

  2. Convert data to byte.

Open file in w mode:

Python 3.6.5 (default, Mar 30 2018, 06:42:10)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> with open('my.txt', 'wb') as f:
...     f.write('123')
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
TypeError: a bytes-like object is required, not 'str'
>>> with open('my.txt', 'w') as f:
...     f.write('123')
...
3
>>>

Convert data to byte:

Python 3.6.5 (default, Mar 30 2018, 06:42:10)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> with open('my.txt', 'wb') as f:
...     f.write('123')
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
TypeError: a bytes-like object is required, not 'str'
>>> with open('my.txt', 'wb') as f:
...     f.write(b'123')
...
3
>>>
Nishant Nawarkhede
  • 8,234
  • 12
  • 59
  • 81