-1

I am working on a Python program that will make infinite text files on a flash drive. This program will be the only thing operating on that flash drive, and I want to check if there is sufficient storage space each time it writes.

If there is, I want to write the file to the drive. If there isn't enough space, I want to do something else with the contents. For example:

def write_file(contents):
    if "Check if there is sufficient storage space on E:\ drive.":
        with open("filename", "w") as file:
            file.write(contents)
    else:
        # Alternative method for dealing with content.

I need to have a good way to find how much space a file.write() operation will take and compare that with the free space on the drive.

Thank you!

Ben Soyka
  • 816
  • 10
  • 25
  • Possible duplicate of [How to get current CPU and RAM usage in Python?](https://stackoverflow.com/questions/276052/how-to-get-current-cpu-and-ram-usage-in-python) – Mr-Programs Sep 06 '18 at 01:05
  • 1
    This is impossible in typical operating systems because there might be sufficient storage at the moment you check and not when you try to write because other applications may have filled the storage. A robust application must be able to tolerate failure while it is writing the data. A pre-check can only be advisory. And the converse is also possible: There may be insufficient storage available when you check but plenty available when you write. One workaround is to allocate all the space for the file, then write the actual data. But, even then, I/O errors (e.g., hardware failures) may occur. – Eric Postpischil Sep 06 '18 at 01:14
  • @BenjaminSoyka: “The best laid plans of mice and men often go awry.” Maybe your solution works today but tomorrow the operating system helpful adds indexing to the storage, thus consuming space on it for the indices. Or, as I wrote, an I/O error occurs. Or you calculate storage for the actual amount of data you are going to write but neglect to count how much the file system needs to add for accounting purposes (tracking file segments and such). And do not know how much to add because tomorrow the drive may be formatted with a different kind of file system. – Eric Postpischil Sep 06 '18 at 01:18

2 Answers2

1

You can get the information of the disk as it is explained here:

import subprocess
df = subprocess.Popen(["df", "path/to/root/of/disk"], stdout=subprocess.PIPE)
output = df.communicate()[0]
device, size, used, available, percent, mountpoint = \
    output.split("\n")[1].split()

Now, use used and available to decide if the disk has enough space.

MTMD
  • 1,162
  • 2
  • 11
  • 23
  • How do I now compare this to how much size writing the file would take? – Ben Soyka Sep 06 '18 at 01:10
  • You need to know what is the encoding in which you want to write the file, and what is the data you are trying to write. For example, if you want to write an integer in binary format you may need 4 bytes. – MTMD Sep 06 '18 at 01:12
  • I would like to write a 1,000 character long string of digits in text format. – Ben Soyka Sep 06 '18 at 01:12
  • If you use Unicode, the size will be approximately length of the string * 2 bytes – MTMD Sep 06 '18 at 01:14
  • You should not reinvent `subprocess.call()` unless you have to. See also https://stackoverflow.com/questions/4256107/running-bash-commands-in-python – tripleee Sep 06 '18 at 05:22
1

This is platform dependent; here is the solution for Windows:

import ctypes
import platform

def get_free_space(dirname):
    free_bytes = ctypes.c_ulonglong(0)
    ctypes.windll.kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(dirname), None, None, ctypes.pointer(free_bytes))
    return free_bytes.value / 1024

if __name__ == "__main__":
    free_space = get_free_space("path\\")
    print(free_space)

If you are on Linux I'm not sure but I found this:

from os import statvfs

st = statvfs("path/")
free_space = st.f_bavail * st.f_frsize / 1024

Your function should look like so:

def write_file(contents):
    if free_space >= len(contents.encode("utf-8")):
        # Write to file.
        file = open("filename", "w")
        file.write(contents)
        file.close()
    else:
        # Alternative method for dealing with content.
Muzol
  • 301
  • 1
  • 11