Я использую pytubefix
для создания загрузчика Youtube.
API позволяет мне писать такой код:
YouTube(url).streams.filter(progressive=True)
Но предположим, что у меня есть строка, хранящаяся в переменной типа
args = "progressive=True"
Как я могу использовать строку args
для вызова функции, как если бы я напрямую указал те же аргументы ключевого слова?
Если я попробую
YouTube(url).streams.filter(args)
это не делает то, что я хочу.
Обычно вы передаете диктат как кварги: stackoverflow.com/questions/5710391/…
Я предполагаю, что ваш загрузчик имеет интерфейс командной строки — иначе откуда взялся url
? Это предполагает, что переменная args
также поступает из командной строки или, возможно, из файла конфигурации. В любом случае вам необходимо использовать специальный синтаксический анализатор (например, argparse , configparser , json и т. д.) для преобразования входных данных в форму, которую можно передавать в качестве аргументов функции.
Вы не можете передавать аргументы ключевого слова в виде строк.
Что вы можете сделать, так это разобрать его самостоятельно в подходящую структуру.
import re
kwargs = {x[0]: x[1] for x in re.findall(r"([^;=]+)=([^;=]+)", args)}
YouTube(url).streams.filter(**kwargs)
Я произвольно добавил ;
в качестве разделителя, чтобы вы могли сказать args = "foo=bar;baz=quux"
Это просто предполагает, что все значения являются строками. Если вам нужно проанализировать, например. "False"
в правильное логическое значение False
или поддерживать числа int
или float
, очевидно, добавьте для этого необходимую логику.
В этом случае это будет передано True
как строка, что, вероятно, потерпит неудачу. Чтобы правильно справиться с этим, вам понадобится больше кода, который будет становиться все более громоздким и плохо определенным. Просто не играть – единственный правильный ответ здесь.
"True"
— это «правда», поэтому это действительно может сработать. Это не будет работать для аргументов ключевых слов, которые должны быть числами, или "False"
vs False
Обновлено, чтобы отметить это в самом ответе.
Вы можете просто разделить строку аргумента на «=", чтобы разделить два компонента. Однако в вашем примере простое разделение даст вам две строки, но вам нужно логическое значение, поэтому...
def myfunc(*, progressive):
print(progressive)
args = "progressive=True"
k, v = args.split(" = ")
myfunc(**{k:v= = "True"})
Ваша входная строка является допустимым кодом Python, поэтому, если строка не получена из пользовательского ввода, вы можете удобно выполнить ее как код Python, чтобы заполнить пустой dict как пространство имен локальных имен, чтобы его можно было распаковать как аргументы ключевого слова для вызова YouTube(url).streams.filter
:
args = "progressive=True"
namespace = {}
exec(args, {}, namespace)
YouTube(url).streams.filter(**namespace)
OTOH, если оно не получено из внешних источников, предоставленных пользователем, тогда зачем вообще использовать строку, а не диктовку…?
Ну, строка может, например, быть получена из файла конфигурации на защищенном хосте, но да, вполне вероятно, что строка предоставлена пользователем. Просто я бы предложил этот подход для полноты картины.
Спасибо, это работает! Я до сих пор не совсем понимаю, почему это должен быть словарь всего, но это работает!
@reChords Всегда пожалуйста. Еще раз имейте в виду, что это решение будет небезопасным, если строка будет получена из пользовательского ввода. Переменные аргументы ключевого слова представляют собой несколько пар имя-значение, поэтому было естественно решено, что dict будет наиболее подходящей структурой данных для их представления.
Почему у вас это вообще строка?