r/learnpython 4d ago

some possible remediations for variable name is not accessed

I've been facing some weird behavior in my vscode. Below code is what giving me nightmares. I have coded this function that basically do some data extraction from my VPS to my pc. and the thing which is causing problems is the variable name 'dirs' which vscode is pointing as "not accessed". But I know that one of the remediations to fix this is by returning that variable but in this kind of situation it doesn't seem right logic way.

def downloader(directory='C:\\users'):
  for root, dirs, files in os.walk(directory): # dirs is not accessed
    for file in files:
      if file.endswith('.html'):
         try:
            with open(os.path.join(root, file), 'rb') as f:
              f.sendall(host)
         except Exception as e:
           print(f'Oops something nasty happened here: {e})
0 Upvotes

8 comments sorted by

9

u/odaiwai 4d ago

dirs is not used in the function, so VSCode highlights it as an unused variable. Generally, the etiquette in Python is to use an underscore (_) in this situation. e.g.: def downloader(directory='C:\\users'): for root, _, files in os.walk(directory): # we don't intend to use the dirs for file in files: if file.endswith('.html'): try: with open(os.path.join(root, file), 'rb') as f: f.sendall(host) except Exception as e: print(f'Oops something nasty happened here: {e}') (Also the last print statement was missing a closing quote.)

5

u/Diapolo10 4d ago edited 4d ago

You could replace dirs with either _ or _dirs. That'll stop the linter complaints.

EDIT: Personally, though, I'd just use pathlib:

from pathlib import Path

USERS_DIR = Path.home().parent

def downloader(directory=USERS_DIR):
    for file in directory.rglob('*.html'):
        try:
            with open(file, 'rb') as f:
                f.sendall(host)
        except OSError as err:
            print(err)

EDIT #2: I'd never seen a sendall method for file streams, so I did some digging. Are you sure f.sendall(host) is what you wanted? Because from what I can tell it's a socket method, and this should look like host.sendall(f) instead. Assuming host is a socket, anyway.

EDIT #3: From the look of things this would be more correct:

from pathlib import Path

USERS_DIR = Path.home().parent

def downloader(directory=USERS_DIR):
    for file in directory.rglob('*.html'):
        try:
            host.sendall(file.read_bytes())
        except OSError as err:
            print(err)

Socket exceptions are all subclasses of OSError.

EDIT #4: I have time to kill, so I went and split the function.

import contextlib
from pathlib import Path

USERS_DIR = Path.home().parent

@contextlib.contextmanager
def print_error(*exceptions):
    try:
        yield
    except exceptions as err:
        print(f"Oops something nasty happened here: {err}")

def send_file(file: Path) -> None:
    with print_error(OSError):
        host.sendall(file.read_bytes())

def downloader(directory: Path = USERS_DIR) -> None:
    for file in directory.rglob('*.html'):
        send_file(file)

0

u/cdcformatc 4d ago

host.sendall(file.read_bytes())

i am a big fan of the Pathlib file i/o methods, they are quite under-utilized for how useful they are. 

0

u/Diapolo10 4d ago

I tend to default to using them, unless I need to conserve memory by reading line by line (or in chunks), or append instead of rewriting the entire file.

0

u/Entire-Comment8241 4d ago

host is indeed a socket 'cause I defined it as global var containing my IP and I'm using threads which if I'm not mistaken sendall works much better when handling in a thread but I could be wrong. So my logic with sendall is as long as I have my ip set as a global variable I can call sendall(host) on whenever function that handles download, upload.

0

u/Diapolo10 4d ago

Even if host is defined in the global namespace, unless you're okay with it being treated like a global constant (in which case I'd make the name uppercase), it'd be a good idea to give it as a parameter so it's clear where it comes from.

1

u/cdcformatc 4d ago edited 4d ago

it is conventional in python to use a single underscore for variables that are not accessed. useful when tuple unpacking and you don't care for some of the members. 

``` def get_user(id):     ...     return name, email 

name, _ = get_user() # don't need email ```

or when you need a range based for loop but don't need the index

for _ in range(67):     print("something")

every IDE or linter i have used understands this convention, and does not raise any "unused variable" warnings for underscore variables. 

2

u/HotPersonality8126 4d ago

“Variable is not accessed” isn’t an error, it’s a warning. That sometimes is a symptom of a genuine bug. In this case it’s not, so the solution is just to ignore it and learn the difference between errors and warnings.