如何以编程方式将数据输入 python 'input()' 提示?

How do I programmatically feed data into a python 'input()' prompt?

我正在为 Spotify API 使用 python 包装器。

https://spotipy.readthedocs.io/en/latest/#installation

作为授权过程的一部分,Spotify API 让用户在他们的默认网络浏览器中登录 Spotify,然后将他们发送到预定义的(当您向 Spotify 注册应用程序时)REDIRECT_URI.此 REDIRECT_URI 当前设置为 localhost:6969。登录后,它会生成一个 input()(死亡输入),供您将重定向到的 URI 复制粘贴到命令提示符中。

我真的不想让随机的人使用命令提示符。

目标是在 localhost:6969 上打开一个 flask 服务器(起诉我)然后双击它的 /authorize 页面(发送到 oauth2 登录然后捕获代码)

http://flask.pocoo.org/docs/1.0/

所以-

我将我的 Flask 装备和 spotify 捕手放在 jflask.py:

from flask import Flask, request, redirect, session
from requests_oauth2 import OAuth2
from spotipy import Spotify
import spotipy.util as util
import requests
import datetime

app = Flask(__name__)

spotify_auth = OAuth2(
  client_id='e33c6fa0d6a249ccafa232a9cf62a616',
  client_secret='a43b0b6a4de14b97b4e468459e0f7824',
  redirect_uri="http://localhost:6969/authorize",
  site="https://accounts.spotify.com",
  authorization_url="/authorize",
  token_url="/api/token",
  scope_sep=" "
)

# and then use this url as a link within a public login view
print(spotify_auth.authorize_url(
  scope=["user-read-recently-played", "user-top-read"],
  response_type="code"
  )
)
# and have an authorize route that can direct you to Spotify or handle you 
#being redirected back here from Spotify
@app .route('/authorize')
def authorize():

  print('triggered')

  error = request.args.get("error")
  if error:
    abort(404)

  code = request.args.get("code")
  if code:
    data = spotify_auth.get_token(
      code=code,
      grant_type="authorization_code",
    )
    access_token = data["access_token"]
    refresh_token = data["refresh_token"]
    scopes = data["scope"].split()
    self.sp = spotipy.Spotify(auth=access_token)
    print(access_token)
    return self.sp
  else:
    print('code aint defined hoe')
    return redirect(spotify_auth.authorize_url(
      scope=["user-read-recently-played", "user-top-read"],
      response_type="code",
      #state=session['state']
    ))

if __name__ == '__main__':
  app.run(host='localhost', port=6969)

我用 master.py:

生成它
from subprocess import Popen, PIPE
import webbrowser

jflask=Popen(['python', 'jflask.py'])

webbrowser.open('http://localhost:6969/authorize')

我已经尝试过将 Popen 与 stdout=PIPE 一起使用。经过进一步研究,我很确定这也阻碍了我的成功。该规范旨在与 subprocess.communicate()

一起使用

https://docs.python.org/3/library/subprocess.html#subprocess.PIP

谢谢大家的帮助。

您可以尝试修改util模块。 用 response = raw_input() 替换 try-except 块:

response = sys.stdin.readline().strip()

如果尚未导入 sys,请不要忘记导入它。

这应该允许正常的 PIPE-ing。

或者您可以使用 pexpect 库而不是 subprocess 模块。它知道如何处理调整终端的 fcntl 标志或在 Windows.

上使用 mscvrt 的输入

另外,当 PIPE-ing 数据时,不要忘记 raw_input()、input() 或 sys.stdin.readline() 在接收到适当的结束之前不会 return的线条字符。 “\r”、“\n”或“\r\n”。您之前是否已授权发送?URL?

Spotipy 的 prompt_for_user_token 方法是作为一种快速而肮脏的方法提供的,允许在本地使用该模块的人起床 运行 并且不打算成为应该直接构建的代码如果您希望任意用户能够通过网站对自己进行身份验证。由于您有一个 Flask 应用程序,您可能应该拥有它和您的 Spotipy 代码通过导入直接交互,而不是使用管道和标准 i/o.

需要注意的一些事项是:

  • Flask-Login 如果您想管理登录网站的用户
  • 除了访问令牌(客户端凭据管理器或 requests 会话)之外,将身份验证传递给 spotipy.Spotify 的替代方法。这些其他方法允许 Spotipy 客户端在访问令牌在使用中过期时刷新访问令牌,处理用户撤销等。
  • requests-oauth2(请注意,这只是许多 OAuth2 Python 库中的一个,可能不是最好的)这使得所有授权的东西更加方便,并允许你做一些事情喜欢:
# import Flask things, requests-oauth2, 
from requests_oauth2 import OAuth2
from spotipy import Spotify
from flask import redirect

spotify_auth = OAuth2(
    client_id=os.environ["SPOTIFY_CLIENT_ID"],
    client_secret=os.environ["SPOTIFY_CLIENT_SECRET"],
    redirect_uri=f"http://{os.environ['HOST_NAME']}/authorize",
    site="https://accounts.spotify.com",
    authorization_url="/authorize",
    token_url="/api/token",
    scope_sep=" "
)

# and then use this url as a link within a public login view
spotify_auth.authorize_url(
    scope=["user-read-recently-played", "user-top-read"],
    response_type="code"
)

# and have an authorize route that can direct you to Spotify or handle you being redirected back here from Spotify
@app.route('/authorize')
def authorize():

    error = request.args.get("error")
    if error:
        abort(404)

    code = request.args.get("code")
    if code:
        data = spotify_auth.get_token(
            code=code,
            grant_type="authorization_code",
        )
        access_token = data["access_token"]
        refresh_token = data["refresh_token"]
        scopes = data["scope"].split()
        spotify_client = spotipy.Spotify(auth=access_token)
    else:
        return redirect(spotify_auth.authorize_url(
            scope=["user-read-recently-played", "user-top-read"],
            response_type="code",
            state=session['state']
        ))

第一次访问 /authorize 时,它会将用户重定向到 Spotify 的登录页面。但是当用户在那里成功登录时,它会将用户重定向回 Flask 站点(返回 /authorize),而不是执行 prompt_for_user_token().

的 copy/paste 部分

一旦他们回到 /authorize,这次有一个 code 请求参数 - 因此它会发出 OAuth2 客户端到提供者请求,为您将此代码转换为访问令牌。

这和 prompt_for_user_token 都遵循相同的方法:

  1. 获取 Spotify 授权 URL 以引导用户登录
  2. 处理来自 Spotify 登录的重定向 - Flask 通过接收来自 Spotify 重定向到的 URL 的输入来做到这一点,而 prompt_for_user_token 通过让你 copy/paste [=56] 来做到这一点=] 来自不存在的网页。
  3. 进行调用以将代码转换为用户的访问和刷新令牌。

我可能对这段代码进行了一些改动,因为它是从我的 Spotify 集成的旧 Flask 实现中挑选出来的。这是一个 more complete gist 但我很确定很多 SQLAlchemy 的东西,授权视图,是相当糟糕的,所以用一点盐来接受它。