File descriptors are a low-level facility for working with files directly provided by the OS kernel. A file descriptor is an integer that identifies the open file in a table of open files kept by the kernel for each process. A number of system calls accept file descriptors, but they are not convenient to work with, typically requiring fixed-width buffers, multiple retries in certain conditions, and manual error handling.
File objects are Python classes that wrap file descriptors to make working with files more convenient and less error-prone. For example, they provide error-handling, buffering, line-by-line reading and are closed when garbage collected.