Python argparse - pass WITHOUT values โ€‹โ€‹to command line

I think I don't understand something general about python argparse.

I'm trying to use the Google YouTube API for a python script, but I don't understand how to pass values โ€‹โ€‹to a script without using the command line.

For example, here is an example for the API. The examples on github and elsewhere show this example as being called from the command line, where the argparse values โ€‹โ€‹are passed from when the script is called.

I don't want to use the command line. I am creating an application that uses a decorator to get credentials for a user, and when that user wants to upload them to their YouTube account, they submit a form, which then calls this script and has argparse values โ€‹โ€‹passed to it.

How can I pass argparser values โ€‹โ€‹(see below some of the code in YouTube upload API script) from another python script?

if __name__ == '__main__':
    argparser.add_argument("--file", required=True, help="Video file to upload")
    argparser.add_argument("--title", help="Video title", default="Test Title")
    argparser.add_argument("--description", help="Video description",
        default="Test Description")
    argparser.add_argument("--category", default="22",
        help="Numeric video category. " +
            "See https://developers.google.com/youtube/v3/docs/videoCategories/list")
    argparser.add_argument("--keywords", help="Video keywords, comma separated",
        default="")
    argparser.add_argument("--privacyStatus", choices=VALID_PRIVACY_STATUSES,
        default=VALID_PRIVACY_STATUSES[0], help="Video privacy status.")
    args = argparser.parse_args()

    if not os.path.exists(args.file):
        exit("Please specify a valid file using the --file= parameter.")

    youtube = get_authenticated_service(args)
    try:
        initialize_upload(youtube, args)
    except HttpError, e:
        print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content)

      


EDIT: As requested, here is a traceback for the 400 error I get using either the standard method to initialize the dictionary or using argparse to create the dictionary. I thought I was getting this because of the poorly formed parameters, but maybe not:

Traceback (most recent call last):
  File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 1535, in __call__
    rv = self.handle_exception(request, response, e)
  File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 1529, in __call__
    rv = self.router.dispatch(request, response)
  File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 1278, in default_dispatcher
    return route.handler_adapter(request, response)
  File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 1102, in __call__
    return handler.dispatch()
  File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 572, in dispatch
    return self.handle_exception(e, self.app.debug)
  File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "C:\Users\...\testapp\oauth2client\appengine.py", line 796, in setup_oauth
    resp = method(request_handler, *args, **kwargs)
  File "C:\Users\...\testapp\testapp.py", line 116, in get
    resumable_upload(insert_request)
  File "C:\Users\...\testapp\testapp.py", line 183, in resumable_upload
    status, response = insert_request.next_chunk()
  File "C:\Users\...\testapp\oauth2client\util.py", line 129, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "C:\Users\...\testapp\apiclient\http.py", line 874, in next_chunk
    return self._process_response(resp, content)
  File "C:\Users\...\testapp\apiclient\http.py", line 901, in _process_response
    raise HttpError(resp, content, uri=self.uri)
HttpError: <HttpError 400 when requesting https://www.googleapis.com/upload/youtube/v3/videos?alt=json&part=status%2Csnippet&uploadType=resumable returned "Bad Request">

      

+3


source to share


3 answers


Whether this is the best approach or not, you really need to figure out. But using argparse without the command line is easy . I do this all the time because I have batches that can be run from the command line. Can also be called by other code - which is great for unit testing as already mentioned. For example, argparse is especially good with default parameters.

Starting with your sample.

import argparse

argparser = argparse.ArgumentParser()
argparser.add_argument("--file", required=True, help="Video file to upload")
argparser.add_argument("--title", help="Video title", default="Test Title")
argparser.add_argument("--description", help="Video description",
    default="Test Description")
argparser.add_argument("--category", default="22",
    help="Numeric video category. " +
        "See https://developers.google.com/youtube/v3/docs/videoCategories/list")
argparser.add_argument("--keywords", help="Video keywords, comma separated",
    default="")
VALID_PRIVACY_STATUSES = ("private","public")
argparser.add_argument("--privacyStatus", choices=VALID_PRIVACY_STATUSES,
    default=VALID_PRIVACY_STATUSES[0], help="Video privacy status.")

#pass in any positional or required variables.. as strings in a list
#which corresponds to sys.argv[1:].  Not a string => arcane errors.
args = argparser.parse_args(["--file", "myfile.avi"])

#you can populate other optional parameters, not just positionals/required
#args = argparser.parse_args(["--file", "myfile.avi", "--title", "my title"])


print vars(args)

#modify them as you see fit, but no more validation is taking place
#so best to use parse_args.
args.privacyStatus = "some status not in choices - already parsed"
args.category = 42

print vars(args)

#proceed as before, the system doesn't care if it came from the command line or not
# youtube = get_authenticated_service(args)    

      



output:

{'category': '22', 'description': 'Test Description', 'title': 'Test Title', 'privacyStatus': 'private', 'file': 'myfile.avi', 'keywords': ''}
{'category': 42, 'description': 'Test Description', 'title': 'Test Title', 'privacyStatus': 'some status not in choices - already parsed', 'file': 'myfile.avi', 'keywords': ''}

      

+4


source


Calling parse_args

with your own list of strings is a common testing technique argparse

. If you don't give parse_args

this list, it uses sys.argv[1:]

- that is, the lines that the shell gives. sys.argv[0]

is the name of the strip.

args = argparser.parse_args(['--foo','foovalue','barvalue'])

      

It's also easy to build an object args

.

args = argparse.Namespace(foo='foovalue', bar='barvalue')

      

In fact, if you are typing args

from a call parse_args

, it should look something like this. As described in the documentation, Namespace

is a simple object and values โ€‹โ€‹are attributes. Therefore, it is easy to create your own class Namespace

. Everything args

should be what returns the corresponding value when used as:

x = args.foo
b = args.bar

      

Also, as noted in the docs, vars(args)

turns this namespace into a dictionary. Some code likes to use a dictionary, but obviously these youtub functions need Namespace

(or equivalent).

get_authenticated_service(args)
initialize_upload(youtube, args)

      



https://docs.python.org/3/library/argparse.html#beyond-sys-argv

https://docs.python.org/3/library/argparse.html#the-namespace-object


https://developers.google.com/youtube/v3/guides/uploading_a_video?hl=id-ID

It has get_authenticated_service

and initialize_upload

code

def initialize_upload(youtube, options):
  tags = None
  if options.keywords:
    tags = options.keywords.split(",")

  body=dict(
    snippet=dict(
      title=options.title,
      description=options.description,
      tags=tags,
      categoryId=options.category
    ),
    status=dict(
      privacyStatus=options.privacyStatus
    )
  )
 ....

      

args

from the parser options

it uses like options.category

, options.title

etc. You can replace any other object that has the same behavior and required attributes.

+4


source


Why are you using argparse if you don't want to use the command line? Argparse is a module created for parsing command line arguments. You cannot pass argparse value in other ways.

I think what you want is a web application rendering an html form making a POST request to some server handler that will pass the value from the form to the api call connect to youtube and execute your python code. Argparse is not required for this at all. You can just take the value from the form and pass it to your api call.

0


source







All Articles