Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Variable Scope for Scripts
#1
I just came across the book Code Complete, 2nd Ed on amazon. It comes with a checklist to ensure you write maintainable code.

Under Chapter 10: General Issues In Using Variables
Other General Issues in Using Data (p. 17)

One of the points says:
Quote:Do all variables have the smallest scope possible?

When referring to variable scope, do they mean large scale applications and using classes to achieve encapsulation? Suppose I had a script that doesn't use classes, but a List and functions to do certain tasks, example, a backup script:

def read_data_from_file(file_to_read):
    #code to read from file and build list
    return list_of_files

def copy_files_to_backup_folder(file_to_copy):
    #code to copy files

file_name="some/path/to/file"
files_to_backup = read_data_from_file(file_name)

for f in files_to_backup:
    copy_files_to_backup_folder(f)
Do you have to worry about variable scope when writing scripts for common admin tasks? In this case file_name?

How would you properly declare it to limit the variable scope as suggested by the checklist/book?

When should you worry about variable scope?
Reply
#2
(Dec-01-2017, 03:34 AM)QueenSvetlana Wrote: Do you have to worry about variable scope when writing scripts for common admin tasks? In this case file_name?
That approach is fine,
also function first that that keep code in local scope(or namespace is common way to describe it in Python).
Then have some variables in global namespace last,that run it.

There are 4 basic scopes,the LEGB, Local, Enclosing, Global and Builtin.
Essentially, the only thing in Python that introduces a new scope is a function definition.
Classes are a bit of a special case in that anything defined directly in the body is placed in the class's namespace.

There are two functions globals() and locals() which show you the contents two of these namespaces.
The Builtin namespace can be look at like this.
>>> import builtins
>>> dir(builtins)
['ArithmeticError',
 'AssertionError',
........
QueenSvetlana Wrote:When should you worry about variable scope
Not so much to worry about,Classes and Functions keep code outside of global namespace.
Try to avoid global variables Wall at all cost,is a good rule.
Reply
#3
(Dec-01-2017, 02:40 PM)snippsat Wrote: Try to avoid global variables Wall at all cost,is a good rule.

The way I've declared file_name and files_to_backup are not in a global way, correct? The problem is these two variables might be used else where in my script, keeping them hidden inside a function will make it more difficult to use. You could return a dictionary of items, but it seems unnecessarily complicated.

This python script could as easily have been a bash/powershell script, and in those you don't worry about variable scope. The only way to hide a variable is inside a function.
Reply
#4
(Dec-01-2017, 02:59 PM)QueenSvetlana Wrote: The way I've declared file_name and files_to_backup are not in a global way, correct?
That's not correct the are in Global namespace,
so the are global variables in that code,
but they are fine as the are the last step and can not interfere with other stuff.

To take a look,i do this so only new stuff in Global namespace is shown so it don't look so messy.
>>> from pprint import pprint

>>> def read_data_from_file(file_name):
    '''In Local namespace'''
    foo = '/bar'
    bar = 100
    return file_name + foo

# We are in Global namespace so these are global variables
>>> file_name = "some/path/to/file"
>>> files_to_backup = read_data_from_file(file_name)

>>> pprint({key: val for key, val in globals().items() if '__' not in key})
{'file_name': 'some/path/to/file',
 'files_to_backup': 'some/path/to/file/bar',
 'pprint': <function pprint at 0x03454CD8>,
 'read_data_from_file': <function read_data_from_file at 0x03454C90>}
See that foo and bar is not seen in Global namespace,have to call function read_data_from_file.
QueenSvetlana Wrote:The problem is these two variables might be used else where in my script, keeping them hidden inside a function will make it more difficult to use. You could return a dictionary of items, but it seems unnecessarily complicated. 
It's not so complicated you make the call  when needed or function can also bye passed to other function.
If all this get to complicated,then it can be time to think of using Classes to structure code.
QueenSvetlana Wrote:The only way to hide a variable is inside a function.
Both function and classes(own namespace),keep variables local so they don't pollute Global namespace.
Reply
#5
To prevent the global namespace from getting messy you can encapsulate your globals in a class thus giving them there own namespace.
Example:
class Config(object):
    timeout = 0.5
    url = 'http://spam.com/eggs'

def get(url, timeout=Config.timeout):
    return somelib.get(url, timeout=timeout)
Reply
#6
(Dec-01-2017, 06:01 PM)snippsat Wrote:
(Dec-01-2017, 02:59 PM)QueenSvetlana Wrote: The way I've declared file_name and files_to_backup are not in a global way, correct?
That's not correct the are in Global namespace,
so the are global variables in that code,
but they are fine as the are the last step and can not interfere with other stuff.

Suppose I rewrote my script to look like this:

def read_data_from_file(file_to_read):
    #code to read from file and build list
    return list_of_files
 
def copy_files_to_backup_folder(file_to_copy):
    #code to copy files
    
def is_backup_successful():
    #code to verify that the a compressed file was created 
    
def write_log_file(file_name):
    #code to generate a log file 
 
file_name="some/path/to/file"
files_to_backup = read_data_from_file(file_name)
 
for f in files_to_backup:
    copy_files_to_backup_folder(f)

is_backup_successful()
write_log_file(file_name):
Notice that there is no specific reason why my backup script should be written in Python. I'm not even using what OOP has to offer to create my script because as it is right now, I don't need too. I could have just used Powershell(Windows 7+) or a Bash script(Linux). In a case such as this, where my Python script could easily be transferred to a shell script, is using global variables the way I have a concern?

My script has a simple reason to exist, create a backup, and write a log file, nothing more. For simple tasks such as this, are global variables a problem? I understand that if my problem were to evolve then, I might consider using classes. For example, suppose if I need to transfer my backup directory to a network drive, and also be able to pull the latest backup, and restore, and I also want to add different compression formats. Now my problem is becoming more complex and the use for classes becomes necessary.
Reply
#7
(Dec-01-2017, 07:40 PM)QueenSvetlana Wrote: , is using global variables the way I have a concern?
No really,i like to do if __name__ == '__main__': as a natural way to see that script end.
Also make it easier to test,if import code it don't automatically run.
So here is not much exposed before doing the final call.
def read_data_from_file(file_to_read):
    #code to read from file and build list
    return list_of_files

def copy_files_to_backup_folder(file_to_copy):
    #code to copy files
    pass

def is_backup_successful():
    #code to verify that the a compressed file was created
    pass

def write_log_file(file_name):
    #code to generate a log file
    pass

def backup(file_name):
    files_to_backup = read_data_from_file(file_name)
    for f in files_to_backup:
        copy_files_to_backup_folder(f)
    is_backup_successful()
    write_log_file(file_name)

if __name__ == '__main__':
    # Here do last step that start it
    file_name = "some/path/to/file"
    backup(file_name)
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How to create a variable only for use inside the scope of a while loop? Radical 10 1,681 Nov-07-2023, 09:49 AM
Last Post: buran
  Library scope mike_zah 2 834 Feb-23-2023, 12:20 AM
Last Post: mike_zah
  Scope of variable confusion Mark17 10 2,828 Feb-24-2022, 06:03 PM
Last Post: deanhystad
  Variable scope issue melvin13 2 1,529 Nov-29-2021, 08:26 PM
Last Post: melvin13
  Variable scope - "global x" didn't work... ptrivino 5 3,031 Dec-28-2020, 04:52 PM
Last Post: ptrivino
  Python Closures and Scope muzikman 2 1,799 Dec-14-2020, 11:21 PM
Last Post: muzikman
  Block of code, scope of variables and surprising exception arbiel 8 3,399 Apr-06-2020, 07:57 PM
Last Post: arbiel
  Help with Global/Coerced Variable (Understanding Scope) Rev2k 6 3,477 Jan-09-2020, 03:43 AM
Last Post: Rev2k
  Solving a scope issue profconn1 4 2,561 Nov-01-2019, 07:46 PM
Last Post: profconn1
  Namespace and scope difference Uchikago 9 4,579 Jul-03-2019, 03:36 PM
Last Post: Uchikago

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020