【问题标题】:Youtube Data API V3 returning ssl.SSLWantWriteError: The operation did not complete (write) error even though it was working beforeYoutube Data API V3 返回 ssl.SSLWantWriteError: The operation did not complete (write) error 即使它之前工作过
【发布时间】:2020-12-16 03:20:57
【问题描述】:

我正在尝试编写一个为我上传视频的机器人,我已经让它工作并用它上传了一些视频。突然它似乎已经停止工作,现在只返回以下错误:

ssl.SSLWantWriteError:操作未完成(写入)(_ssl.c:2408)

我不明白这是从哪里来的,为什么,互联网没有帮助,我试图阅读它来自哪里的文件,但这样做并没有更聪明。

这是我尝试上传视频的代码:

def upload(beatName, mainArtist, keywords, oneLiner):
    CLIENT_SECRET_FILE = 'client_secret_file.json'
    API_NAME = 'youtube'
    API_VERSION = 'v3'
    SCOPES = ['https://www.googleapis.com/auth/youtube.upload']

    service = Create_Service(CLIENT_SECRET_FILE, API_NAME, API_VERSION, SCOPES)

    upload_date_time = DT.datetime(2020, 8, 27, 12, 30, 0).isoformat() + '.000Z'

    title = "xxx"
    description = 'xxx'

    request_body = {
        'snippet': {
            'categoryI': 10,
            'title': title,
            'description': description,
            'tags': keywords
        },
        'status': {
            'privacyStatus': 'private',
            'publishAt': upload_date_time,
            'selfDeclaredMadeForKids': False,
        },
        'notifySubscribers': True
    }

    mediaFile = MediaFileUpload('E:\Everything.mp4')

    response_upload = service.videos().insert(
        part = 'snippet,status',
        body = request_body,
        media_body = mediaFile
    ).execute()

错误的原因可能是什么?我该如何寻找解决方案?

编辑:

按照评论者的建议更新我的客户后(确实是一个版本太旧),我现在收到了一个不同的错误,我也无法处理:

oauthlib.oauth2.rfc6749.errors.UnsupportedGrantTypeError: (unsupported_grant_type) Invalid grant_type: 

[INFO   ] [Base        ] Leaving application in progress...
 Traceback (most recent call last):
   File "C:/Users/ricsi/Desktop/Automatic Beat Uploader/main.py", line 34, in <module>
     AutomaticUploader().run()
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\kivy\app.py", line 855, in run
     runTouchApp()
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\kivy\base.py", line 504, in runTouchApp
     EventLoop.window.mainloop()
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\kivy\core\window\window_sdl2.py", line 747, in mainloop
     self._mainloop()
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\kivy\core\window\window_sdl2.py", line 479, in _mainloop
     EventLoop.idle()
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\kivy\base.py", line 342, in idle
     self.dispatch_input()
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\kivy\base.py", line 327, in dispatch_input
     post_dispatch_input(*pop(0))
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\kivy\base.py", line 233, in post_dispatch_input
     listener.dispatch('on_motion', etype, me)
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\kivy\core\window\__init__.py", line 1402, in on_motion
     self.dispatch('on_touch_down', me)
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\kivy\core\window\__init__.py", line 1418, in on_touch_down
     if w.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\kivy\uix\widget.py", line 549, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\kivy\uix\widget.py", line 549, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\kivy\uix\behaviors\button.py", line 151, in on_touch_down
     self.dispatch('on_press')
   File "kivy\_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
   File "kivy\_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1098, in kivy._event.EventObservers._dispatch
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\kivy\lang\builder.py", line 64, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "C:\Users\ricsi\Desktop\Automatic Beat Uploader\automaticuploader.kv", line 53, in <module>
     on_press: root.upload()
   File "C:/Users/ricsi/Desktop/Automatic Beat Uploader/main.py", line 27, in upload
     upload(beatName, mainArtist, keywords, oneLiner)
   File "C:\Users\ricsi\Desktop\Automatic Beat Uploader\youtube.py", line 144, in upload
     service = Create_Service(CLIENT_SECRET_FILE, API_NAME, API_VERSION, SCOPES)
   File "C:\Users\ricsi\Desktop\Automatic Beat Uploader\Google.py", line 31, in Create_Service
     cred = flow.run_local_server()
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\google_auth_oauthlib\flow.py", line 460, in run_local_server
     self.fetch_token(authorization_response=authorization_response)
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\google_auth_oauthlib\flow.py", line 281, in fetch_token
     self.client_config['token_uri'], **kwargs)
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\requests_oauthlib\oauth2_session.py", line 360, in fetch_token
     self._client.parse_request_body_response(r.text, scope=self.scope)
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\oauthlib\oauth2\rfc6749\clients\base.py", line 421, in parse_request_body_response
     self.token = parse_token_response(body, scope=scope)
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\oauthlib\oauth2\rfc6749\parameters.py", line 431, in parse_token_response
     validate_token_parameters(params)
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\oauthlib\oauth2\rfc6749\parameters.py", line 438, in validate_token_parameters
     raise_from_error(params.get('error'), params)
   File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\oauthlib\oauth2\rfc6749\errors.py", line 405, in raise_from_error
     raise cls(**kwargs)
 oauthlib.oauth2.rfc6749.errors.UnsupportedGrantTypeError: (unsupported_grant_type) Invalid grant_type: 

根据请求添加调试日志(敏感数据已更改):

INFO:google_auth_oauthlib.flow:"GET /?state=J4aIHazfWta0WBvU5X5mtHzb6Xh1hT&code=4/3gGqpfkFDfV9nVgE4PkISwAB0pgFkD9-CcukEOhLk_FMxvsj0Ca9CBSpEvBpU0nzN63gbjeP2_WkfMaTgRa3gnA&scope=https://www.googleapis.com/auth/youtube.upload HTTP/1.1" 200 65
DEBUG:requests_oauthlib.oauth2_session:Encoding `client_id` "36097-31saf6e4sdfDAG3amuivcki8vgo3rmfgj.apps.googleusercontent.com" with `client_secret` as Basic auth credentials.
DEBUG:requests_oauthlib.oauth2_session:Requesting url https://oauth2.googleapis.com/token using method POST.
DEBUG:requests_oauthlib.oauth2_session:Supplying headers {'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'} and data {'grant_type': 'authorization_code', 'code': '4/3gGqpfkFDfV9nVgE4PkISwAB0pgFkD9-CcukEOhLk_FMxvsj0Ca9CBSpEvBpU0nzN63gbjeP2_WkfMaTgRa3gnA', 'redirect_uri': 'http://localhost:8080/'}
DEBUG:requests_oauthlib.oauth2_session:Passing through key word arguments {'timeout': None, 'auth': <requests.auth.HTTPBasicAuth object at 0x000001CD14ECFAC8>, 'verify': True, 'proxies': None}.
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): oauth2.googleapis.com:443

DEBUG:urllib3.connectionpool:https://oauth2.googleapis.com:443 "POST /token HTTP/1.1" 400 None
DEBUG:requests_oauthlib.oauth2_session:Request to fetch token completed with status 400.
DEBUG:requests_oauthlib.oauth2_session:Request url was https://oauth2.googleapis.com/token
DEBUG:requests_oauthlib.oauth2_session:Request headers were {'User-Agent': 'python-requests/2.24.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': 'application/json', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 'Content-Length': '172', 'Authorization': 'Basic NjY0NdfwDE0ODEyLXRtbnE0dGddfgEx4azZndTNq3dDU2c3Nodm45tLmGRFwcHMuZ29456FGertxldXNlcmNvbnRlbnQuY29df3Q3E1VXpRDRpNDFqUTlfeTY5bw=='}
DEBUG:requests_oauthlib.oauth2_session:Request body was grant_type=authorization_code&code=4%2F3gEwdk40hc5ItuvD-JBsg4fdjKsx534dhf7df5KtdGhxIGS5646gh56K61-tW5cxOz34tG6Sg8Adysic3u12I346StHbT9Y4564Shg&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F
DEBUG:requests_oauthlib.oauth2_session:Response headers were {'Content-Type': 'application/json; charset=utf-8', 'Vary': 'Origin, X-Origin, Referer', 'Content-Encoding': 'gzip', 'Date': 'Thu, 27 Aug 2020 22:08:18 GMT', 'Server': 'scaffolding on HTTPServer2', 'Cache-Control': 'private', 'X-XSS-Protection': '0', 'X-Frame-Options': 'SAMEORIGIN', 'X-Content-Type-Options': 'nosniff', 'Alt-Svc': 'h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"', 'Transfer-Encoding': 'chunked'} and content {
  "error": "unsupported_grant_type",
  "error_description": "Invalid grant_type: "
}.
DEBUG:requests_oauthlib.oauth2_session:Invoking 0 token response hooks.
Traceback (most recent call last):
  File "<input>", line 12, in <module>
  File "C:\Users\ricsi\Desktop\Automatic Beat Uploader\Google.py", line 31, in Create_Service
    cred = flow.run_local_server()
  File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\google_auth_oauthlib\flow.py", line 460, in run_local_server
    self.fetch_token(authorization_response=authorization_response)
  File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\google_auth_oauthlib\flow.py", line 281, in fetch_token
    self.client_config['token_uri'], **kwargs)
  File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\requests_oauthlib\oauth2_session.py", line 360, in fetch_token
    self._client.parse_request_body_response(r.text, scope=self.scope)
  File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\oauthlib\oauth2\rfc6749\clients\base.py", line 421, in parse_request_body_response
    self.token = parse_token_response(body, scope=scope)
  File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\oauthlib\oauth2\rfc6749\parameters.py", line 431, in parse_token_response
    validate_token_parameters(params)
  File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\oauthlib\oauth2\rfc6749\parameters.py", line 438, in validate_token_parameters
    raise_from_error(params.get('error'), params)
  File "C:\Users\ricsi\Anaconda3\envs\Automatic Beat Uploader\lib\site-packages\oauthlib\oauth2\rfc6749\errors.py", line 405, in raise_from_error
    raise cls(**kwargs)
oauthlib.oauth2.rfc6749.errors.UnsupportedGrantTypeError: (unsupported_grant_type) Invalid grant_type: 

【问题讨论】:

  • edit您的帖子,添加完整的异常堆栈跟踪(作为文本!)。还要确保您已经安装了最新版本的 Google APIs 客户端库 for Python;用pip show google-api-python-client查看当前版本;那么如果不是the newestpip install --update google-api-python-client
  • 我会,但另一个错误现在取代了这个错误(我没有改变任何东西)所以我现在无法复制它.. google 的 api 很痛苦
  • 无论如何,更新你的客户端库。
  • 是的,我做到了,就在这时出现了新的错误(我想我确实改变了一些东西)
  • 然后发布该错误的完整堆栈跟踪。 (如果只是编辑他/她的原始帖子,那么这里没有问题。)

标签: python ssl youtube-data-api


【解决方案1】:

(免责声明:这不是答案,只是尝试解决 OP 的问题。)

请在您的源文件中定义以下派生类:

class InstalledAppFlow2(InstalledAppFlow):

    def fetch_token(self, **kwargs):
        kwargs.setdefault("client_secret", self.client_config["client_secret"])
        kwargs.setdefault("code_verifier", self.code_verifier)
        return self.oauth2session.fetch_token(
            self.client_config["token_uri"],
            include_client_id = True,
            **kwargs)

然后替换

flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES)

flow = InstalledAppFlow2.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES)

InstalledAppFlow2的目的是让flow对象传递给函数OAuth2Session.fetch_token参数include_client_id = True;此参数将指示OAuth2Session.fetch_token 在对服务器进行的授权调用的请求正文中传递client_idclient_secret

然后再次验证为其行Request body 生成的日志文件具有client_id=...client_secret=...。此外,Request header 行不应再有 Authorization: Basic ...

【讨论】:

  • 我这样做了,日志文件请求正文现在具有客户端 ID 和客户端密码,并且标头不再具有基本授权,但同样的错误仍然存​​在。我还仔细检查了客户端密码 json 文件,但似乎是对的。我直接从谷歌云控制台下载的,完全没有修改过,所以应该没有什么问题。
  • 这很不幸。尝试使用 Google 的OAuth Playground。看看我能不能通过步骤号。 2、Exchange authorization code for tokens。请注意,该页面的右侧显示了整个请求和响应文本。
  • 通过尝试使用我自己的 oauth 凭据授权 youtube 数据 api v3,游乐场给了我错误 400:redirect_uri_mismatch
  • 点击OAuth 2.0 Configuration按钮,点击复选框Use your own OAuth credentials,输入您自己的凭据(客户端ID和密码)。
  • 是的,我做到了,也使用了我试图在我的代码中使用的相同范围,但我得到重定向 uri 不匹配
猜你喜欢
  • 2020-12-21
  • 2021-03-16
  • 2019-08-14
  • 1970-01-01
  • 2019-11-14
  • 1970-01-01
  • 1970-01-01
  • 2018-01-21
  • 1970-01-01
相关资源
最近更新 更多