-2

My program reads a file (batch_files) that contains a list of file names containing tranches of data. If batch_files is empty, the code will create a new text file. If batch_files contains file names, the program will append data to the existing file(s).

Here is my original code/pseudo code, which worked in Python 3.5:

    with open(path + batch_files, 'r+', encoding='utf-8') as file_list:
        batch_names = [line.rstrip('\n') for line in file_list]
        series_count = len(batch_names)
        # Initialize an empty batch if none exists.
        if series_count == 0:
            series_count += 1
            Pseudo-code: create file and append file name to `batch_files`
        # Load existing batches.
        for file_name in batch_names:
            with open(path + file_name, 'r', encoding='utf-8') as tranche:
                Pseudo-code: append data to existing file.

In Python 3.6.6, I receive the following error:

PermissionError: [Errno 13] Permission denied:'[error message includes the working directory path without a filename]'

Even though batch_files is empty, i.e. batch_names = [''], len(batch_names) equals 1 (per debugging trace). The code then skips the file initialization subroutine because if series_count == 0 is false. Then the code tries to load a non-existent data file but produces an error because there is no text in file_name.

I tried the following empty list and file tests:

  1. if not batch_names: per this thread.
  2. if os.stat(path + batch_files).st_size == 0: per this thread.

Both versions failed to trigger file initialization. See edits below for more information on getting these solutions to work. Side Note: I am using Notepad++ to ensure batch_files is empty. The file size is 0k. OS is Windows 10.

Why does my code think batch_files isn't empty? How do you suggest I fix the problem?

Edit: Per @saarrrr, the list contains an empty text string, so I used the following code to solve the issue.

Preferred Method:

    batch_list = [line.rstrip('\n') for line in file_list]
    # Remove empty text strings.
    batch_names = list(filter(None, batch_list))
    # Initialize an empty batch if none exists.
    if not batch_names:

Alternatively:

    batch_list = [line.rstrip('\n') for line in file_list]
    batch_names = list(filter(None, batch_list))
    series_count = len(batch_names)
    # Initialize an empty batch if none exists.
    if series_count == 0:

Also, if os.stat(path + batch_files).st_size == 0: will work. This option failed for me initially because I had pointed batch_files to the wrong file.

I don't understand why a list with an empty text string isn't empty. Nor do I understand why my original conditional worked in 3.5 but not 3.6. Explanations of the problem's source or more pythonic solutions are welcome.

Edit 2: Link to Standard Library discussing lists. Nested empty lists are possible. Empty text strings aren't mentioned; however, I'm assuming the same logic applies to other data types, i.e. an empty data type is considered a list element.

  • 4
    Hold up, `batch_names = ['']` means it's not empty, it has an empty string in it. `batch_names = []` is empty. – saarrrr Aug 05 '18 at 01:53
  • I think the problem is you don't have the permission to read/write to the file.... Can you post the whole Error Message? Perhaps just remove your directory path – Gareth Ma Aug 05 '18 at 01:57
  • Are you sure the path is indeed a file? You might be opening a directory instead, which will lead to that error. – RoadRunner Aug 05 '18 at 01:57
  • @DivideByZero can you try to print 'path + batch_files' and check if it is a file instead of a directory – Gareth Ma Aug 05 '18 at 01:58
  • @saarrrr -- I think the empty string is the crux of the problem. Why does a list with an empty string not register as empty? Solution suggestions? – DivideByZero Aug 05 '18 at 02:09

1 Answers1

0

The error message writes PermissionError, which means you don't have the permission to read/write the file(r+ mode means read & write), it doesn't matter of what the file's content is.

Also as @saarrrr pointed out, batch_names = [''] means it has an empty string in it, which is not empty. batch_names = [] is empty.

Gareth Ma
  • 329
  • 2
  • 11
  • The error is produced because the code tries to write to a file that doesn't exist. This happens because the initialization routine is skipped. – DivideByZero Aug 05 '18 at 02:06
  • try `w+` mode? https://stackoverflow.com/questions/2967194/open-in-python-does-not-create-a-file-if-it-doesnt-exist – Gareth Ma Aug 05 '18 at 02:07
  • Also I get this error message when the file doesn't exist: `FileNotFoundError: [Errno 2] No such file or directory: 'foobar.txt'` – Gareth Ma Aug 05 '18 at 02:08
  • As you see from my code, the file to be written to is a concatenation of the path and filename. Filename is drawn from batch_names, which is empty. Thus, the program attempts to write to a path without a file name attached. Thus, I get Errno 13 instead of Errno 2. – DivideByZero Aug 05 '18 at 02:17