I know it sounds complicated and it may not be possible, but I thought I'd try anyway.
So I'm doing some web scraping with Selenium, and any time that I want to run some jQuery on a page, instead of having
driver.execute_script("$('button').parent().click()")
I want to tidy up my code and just have
j('button').parent().click()
I'm attempting to accomplish this by having a class j
and then when you have a function like parent
it just returns another instance of that class.
In these examples I just have it printing the string that will get executed so that it can be tested more easily. And the way I have it the class exists inside a function.
So in this example everything works fine when all the class functions are defined normally, but if you uncomment the for
loop section and define the .parent()
function with exec
then you get the error NameError: name 'j' is not defined
:
def browser():
class j:
def __init__(self, str):
if str[0] == '$':
self.jq = str
else:
self.jq = f"$('{str}')"
def click(self):
output = f"{self.jq}.click()"
print(output)
return j(output)
def parent(self):
return j(f'{self.jq}.parent()')
# functions = 'parent, next, prev'
# for fn in functions.split(', '):
# exec(
# f"def {fn} (self):\n" +
# f" return j(f'{{self.jq}}.{fn}()')"
# )
j('button').parent().click()
browser()
However, if you move everything outside of the browser
function and run everything then there's no error that way also, and that's if you define the functions either way.
I also tried doing exec(code, globals())
but that just gave me a different error message instead: AttributeError: 'j' object has no attribute 'parent'
Is there some way to define functions with exec
in this way and do what I'm try to do?
Edit: This is the entire error message:
Traceback (most recent call last):
File "C:\Users\Rob\Desktop\site\mysite\py\z.py", line 30, in <module>
browser()
File "C:\Users\Rob\Desktop\site\mysite\py\z.py", line 28, in browser
j('button').parent().click()
File "<string>", line 2, in parent
NameError: name 'j' is not defined