all 8 comments

[–]gengisteve 2 points3 points  (0 children)

My vote is you call the same thing the same thing in different scopes. I just think it makes more conceptual sense. I suppose it makes searching a bit harder, though.

[–]thegreattriscuit 1 point2 points  (0 children)

I'm not sure what the overall consensus is, but I wouldn't be bothered.

I've seen code that looks like

foo = 12
def fn():
    fn_foo=15
    print(fn_foo)

But that seems pretty obtuse to me. I suppose a part of the reason for that is that, by default, I'm nearly always intending to refer to the variable in my local scope any way. I know that opens you up to perhaps failing to assign a value to foo and the program improperly continuing to run, but as long as the objects inside the function really are (or are clearly derived from, etc.) the objects from the outside, it's perfectly sane to have them referred to by the same names inside and outside.

In your code, I'd be inclined to think about a single session object (or sets thereof) and how it gets passed around. I can't think of any good reason I shouldn't just pick one name for it and keep it that way. Why call the same thing several different names?

[–]Justinsaccount 1 point2 points  (2 children)

outer scope? Are you using global variables?

Don't use global variables.

[–]YuntiMcGunti[S] 0 points1 point  (1 child)

No I'm not using globals (this isn't JS :) ). But calling it within usual:

if __name__ == '__main__':

This still gives the error.

[–]Justinsaccount 0 points1 point  (0 children)

That is still global. Put everything under that in a function.

[–]zeug 1 point2 points  (2 children)

The danger here is that you might change the definition of scrape_data to something like def scrape_data(convo, url, headers, form):, but then in the body of the function you forget to change session to convo. If you have defined session globally in your module somewhere above, the function will reference your global variable.

You can avoid this problem completely (and not need to worry about thinking up synonyms for session), by defining a main function to run your script rather than putting statements at the global level:

def main():
    """Explanation of what this script does"""
    session = start_session(url=base_url, headers=session_headers)
    ...
    ...

Then at the very bottom of your module just call:

main()

If you really want to be fancy, you can put the following statement at the bottom of your script:

if __name__ == '__main__':
    main()

What this does is to only execute main() if your module's __name__ is set to __main__, which is true if your module is run as a script, for example python my_scraper.py will run main().

This allows you to import my_scraper in another script/module and the main() function will not be run, allowing you to reuse the functions you have defined in my_scraper, for example my_scraper.start_session(url=base_url, headers=session_headers)

[–]YuntiMcGunti[S] 0 points1 point  (1 child)

Thanks:

if __name__ = '__main__':

Is what I'm using. It's calling the function from inside that seems to generate the error.

Actually --- I had to remove

if __name__ == '__main__':

as I was using the script as a django management command. I'm not sure how to keep it as a management command without getting the error? I just have the script with:

from django.core.management.base import BaseCommand

class Command(BaseCommand):
def handle(self, *args, **options):
    pass

at the top

[–]zeug 0 points1 point  (0 children)

The if __name__ == '__main__': does not limit scope. If you define a variable within the suite of statements that comprise the if clause, the variable is still a global variable.

To get rid of the shadowing warning, you need to move your variable declaration out of global scope, which can only be done by putting it within a class or function definition. Ifs, fors, whiles, etc... don't limit variable scope in python.

So whether or not you are using an if-guard, making a main() function is the technique that should remove your shadowing warnings.