TypeError: utf_8_encode() argument 1 must be str, not bytes

TypeError: utf_8_encode() argument 1 must be str, not bytes

作为 Udacity 培训的一部分,我正在研究 RESTful API:

https://www.udacity.com/course/designing-restful-apis--ud388

我收到了起始代码 (find_restaurant.py),任务是完成此代码。我正在尝试逐步完成此代码。

当我运行:“find_restaurant.py”时,它returns下面的回溯。

我已经在互联网上搜索(包括堆栈溢出)并找到了一些相关主题,但是我仍然不明白这个问题。 有人可以帮我 理解 TypeError 吗?

Traceback (most recent call last):

  File "D:\ds_dev\Udacity\fullstack-nanodegree-vm\find_restaurant.py", line 37, in <module>
    find_restaurant("Pizza", "Tokyo, Japan")

  File "D:\ds_dev\Udacity\fullstack-nanodegree-vm\find_restaurant.py", line 23, in find_restaurant
    print(meal_type)

  File "C:\Users\zeerm\.conda\envs\spyder\lib\codecs.py", line 378, in write
    self.stream.write(data)

  File "C:\Users\zeerm\.conda\envs\spyder\lib\codecs.py", line 377, in write
    data, consumed = self.encode(object, self.errors)

TypeError: utf_8_encode() argument 1 must be str, not bytes

geocode.py:

import json
import httplib2


def geocode_location(address_string):
    """Retrieve latitude and longitude for a location string.

    Http GET request to Google Maps API for retrieving latitude and longitude
    for a location string.
    """
    
    address = address_string.replace(" ", "%20")
    key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
    url = (f'https://maps.googleapis.com/maps/api/geocode/json?' +
           f'address={address}&key={key}')
    h = httplib2.Http()
    result = json.loads(h.request(url, 'GET')[1])
    latitude = result['results'][0]['geometry']['location']['lat']
    longitude = result['results'][0]['geometry']['location']['lng']
    return (latitude, longitude)

find_restaurant.py

import json
import sys
import codecs
import httplib2
from geocode import geocode_location

sys.stdout = codecs.getwriter('utf8')(sys.stdout)
sys.stderr = codecs.getwriter('utf8')(sys.stderr)

FOURSQUARE_CLIENT_ID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
FOURSQUARE_CLIENT_SECRET = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

def find_restaurant(meal_type, location):
    """ # TODO: Descripe function."""

    # 1. Use getGeocodeLocation to get the latitude and longitude coordinates of the location string.
    print(meal_type)
    lat_lng = geocode_location(location)
    print(lat_lng)
    # 2.  Use foursquare API to find a nearby restaurant with the latitude, longitude, and mealType strings.
    # HINT: format for url will be something like https://api.foursquare.com/v2/venues/search?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&v=20130815&ll=40.7,-74&query=sushi

    # 3. Grab the first restaurant
    # 4. Get a  300x300 picture of the restaurant using the venue_id (you can change this by altering the 300x300 value in the URL or replacing it with 'orginal' to get the original picture
    # 5. Grab the first image
    # 6. If no image is available, insert default a image url
    # 7. Return a dictionary containing the restaurant name, address, and image url


if __name__ == '__main__':
    find_restaurant("Pizza", "Tokyo, Japan")
    find_restaurant("Tacos", "Jakarta, Indonesia")
    find_restaurant("Tapas", "Maputo, Mozambique")
    find_restaurant("Falafel", "Cairo, Egypt")
    find_restaurant("Spaghetti", "New Delhi, India")
    find_restaurant("Cappuccino", "Geneva, Switzerland")
    find_restaurant("Sushi", "Los Angeles, California")
    find_restaurant("Steak", "La Paz, Bolivia")
    find_restaurant("Gyros", "Sydney, Australia")

codecs.getwriter returns a codecs.StreamWriter 包装流并使用传递给 getwriter 的编码写入流的实例。在问题的代码中,sys.stdoutsys.stderr 被编写器包装,这些编写器将向它们写入 UTF-8 编码的字节

sys.stdout = codecs.getwriter('utf8')(sys.stdout)
sys.stderr = codecs.getwriter('utf8')(sys.stderr)

但是 sys.stdoutsys.stderrtext 流,因此它们的 write 方法需要 str,而不是 Bytes。由于 StreamWriter 正在传递字节,因此发生异常。

像这样覆盖 sys.stdout 是 Python2 中使用的一种技术,用于在管道输出时强制使用特定的输出编码。

在这种特殊情况下,应从代码中删除这两行。如果有必要以非默认编码强制输出 - 那么最好设置 PYTHONIOENCODING 环境变量。