Repository: googleapis/google-api-python-client

Issue:
mediafileupload has no attribute '_fd'
#### Environment details

  - OS: Ubuntu 18.04
  - Python version: 3.7.4
  - pip version: 19.2.3
  - `google-api-python-client` version: current

#### Steps to reproduce

  1. Add simple file upload from example to quickstart example from https://developers.google.com/drive/api/v3/quickstart/python
  2. After running console shows error: attributeerror 'mediafileupload' object has no attribute '_fd'


Discussion:
Hi @Stormwaker,

I'm unable to replicate the error. It looks like you are using [this sample](https://developers.google.com/drive/api/v3/manage-uploads) showing simple uploads.

Could you try again with the code below?
```py
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive']

def main():
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('drive', 'v3', credentials=creds)

    file_metadata = {'name': 'photo.jpg'}
    media = MediaFileUpload('files/photo.jpg',
                            mimetype='image/jpeg')
    file = service.files().create(body=file_metadata,
                                        media_body=media,
                                        fields='id').execute()
    print ('File ID: %s' % file.get('id'))

if __name__ == '__main__':
    main()
```
I've noticed that there was a typo in the path to photo I wanted to upload. So I think that the error might be coming from exception handling. Full error reads:
```
Exception ignored in: <function MediaFileUpload.__del__ at 0x7fe736c88d40>
Traceback (most recent call last):
  File "/home/maccutkiewicz/anaconda3/lib/python3.7/site-packages/googleapiclient/http.py", line 567, in __del__
    self._fd.close()
AttributeError: 'MediaFileUpload' object has no attribute '_fd'
```
:+1: I'm able to replicate it if I misspell the filename.
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/googleapiclient/http.py", line 578, in _del_
    self._fd.close()
AttributeError: 'MediaFileUpload' object has no attribute '_fd'

I got the same error while executing MediaFileUpload() but It's fine to work in the windows machine. Anyone here can please help me. Thanks
When I use the right directory and file address, it doesn't give me this error. My directory path starts with /Users/<myname>/<folder_name>/<file_name>
@NikhilTank35 
```
media = MediaFileUpload('files/photo.jpg',
                            mimetype='image/jpeg')
```
Make sure that `files/photo.jpeg` is a valid path. I was getting the same error, realized that I have no file at `files/photo.jpeg` in my repo. 

Resolving patch:
diff --git a/googleapiclient/http.py b/googleapiclient/http.py
--- a/googleapiclient/http.py
+++ b/googleapiclient/http.py
@@ -573,8 +573,9 @@ def __init__(
       resumable: bool, True if this is a resumable upload. False means upload
         in a single request.
     """
+        self._fd = None
         self._filename = filename
-        fd = open(self._filename, "rb")
+        self._fd = open(self._filename, "rb")
         if mimetype is None:
             # No mimetype provided, make a guess.
             mimetype, _ = mimetypes.guess_type(filename)
@@ -582,11 +583,12 @@ def __init__(
                 # Guess failed, use octet-stream.
                 mimetype = "application/octet-stream"
         super(MediaFileUpload, self).__init__(
-            fd, mimetype, chunksize=chunksize, resumable=resumable
+            self._fd, mimetype, chunksize=chunksize, resumable=resumable
         )
 
     def __del__(self):
-        self._fd.close()
+        if self._fd:
+            self._fd.close()
 
     def to_json(self):
         """Creating a JSON representation of an instance of MediaFileUpload.


Test patch:
diff --git a/tests/test_http.py b/tests/test_http.py
--- a/tests/test_http.py
+++ b/tests/test_http.py
@@ -248,6 +248,10 @@ def test_media_file_upload_to_from_json(self):
         self.assertEqual(500, new_upload.chunksize())
         self.assertEqual(b"PNG", new_upload.getbytes(1, 3))
 
+    def test_media_file_upload_raises_on_file_not_found(self):
+        with self.assertRaises(FileNotFoundError):
+            MediaFileUpload(datafile("missing.png"))
+
     def test_media_file_upload_raises_on_invalid_chunksize(self):
         self.assertRaises(
             InvalidChunkSizeError,