Reputation: 6239
I'd like to know if I can have a parameter list with keywords given inside a string that I can pass into a function? Basically, the parameter list may or may not have keywords, so the parameter list would have variable 'types'. Here's an example of what I'm trying to do:
from bs4 import BeautifulSoup
import urllib.request as urlreq
import my_parameters # can have variable values
# my_parameters.useful_token_concept = ["h1", "class_ = some_class"]
# I want to pass these above parameters into a function; "class_" is
# a keyword, but it's wrapped in a string => gives me problems
url = my_parameters.url
page = urlreq.urlope(url)
pageHtml = page.read()
page.close()
soup = BeautifulSoup(pageHtml)
# something like the following line works:
# params = soup.find("h1", class_ = "some_class")
params = soup.find(*my_parameters.useful_token_concept)
# params = soup.find(my_parameters.useful_token_concept[0],\
# my_parameters.useful_token_concept[1])
# I don't know how long the list of attributes/parameter-list to
# BeautifulSoup's find() function will be, nor do I know what keywords,
# if any, will be passed into find(), as given by a user to my_parameters.
print(params) # should print the html the user wants to scrape.
Upvotes: 0
Views: 179
Reputation: 123463
You could create a string representation of how all the arguments would be passed and use eval()
to turn them into something you could actually use in a real function call:
my_parameters.useful_token_concept = ["h1", "class_ = some_class"]
def func_proxy(*args, **kwargs):
" Just return all positional and keyword arguments. "
return args, kwargs
calling_seq = ', '.join(my_parameters.useful_token_concept)
args, kwargs = eval('func_proxy({})'.format(calling_seq))
print('args:', args) # -> args: (<Header1 object>,)
print('kwargs:', kwargs) # -> kwargs: {'class_': <class '__main__.some_class'>}
parms = soup.find(*args, **kwargs)
Upvotes: 1
Reputation: 881675
Why not just use a better representation? I.e, instead of
my_parameters.useful_token_concept = ["h1", "class_ = some_class"]
use
my_parameters.useful_token_concept = ["h1", {"class_": "some_class"}]
Since these values' representation is up to you, using a dict
to represent keyword parameters is much simpler than encoding them into a string and then having to parse that string back!
Upvotes: 2
Reputation: 174624
You need to split your token list into a dictionary of keyword arguments, and a list of positional arguments.
kwargs = {}
args = []
for i in my_parameters.useful_token_concept:
bits = i.split('=')
if len(bits) > 1:
kwargs[bits[0].strip()] = bits[1].strip()
else:
args.append(bits[0].strip())
params = soup.find(*args, **kwargs)
Upvotes: 1