Azure Pipeline Python task arguments - python

My Need is to execute a python script in my azure pipeline with additional command line arguments.
I'm able to run the script inline successfully with this code & the output I get is as expected:
1- for print ('Hello ', args.svc) as ('Hello, 'Service_De')
2- for print ('Hello ', args.env) as ('Hello, 'Dev')
- task: PythonScript#0
inputs:
scriptSource: inline
script: |
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--svc")
parser.add_argument("--env")
args = parser.parse_args()
print ('Hello ', args.svc)
print ('Hello ', args.env)
arguments: --svc ${{parameters.service}}_${{parameters.environment}}
--env ${{parameters.environment}}
I have 2 issues that I need help with:
Issue #1:
When I separate my service & environment arguments and update my python task as a combination of both arguments, the script gives me an error
print ('Hello ', args.svc_args.env)
I am not able to format the python code properly. I ideally want the output as ('Helo','Service_Dev')
- task: PythonScript#0
inputs:
scriptSource: inline
script: |
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--svc")
parser.add_argument("--env")
args = parser.parse_args()
print ('Hello ', args.svc_args.env)
arguments: --svc ${{parameters.service}}
--env ${{parameters.environment}}
Issue #2::
When I execute the same working code using the filepath option, it fails to execute and give me an error:
IOError: [Errno 2] No such file or directory: './group_vars/args.svc.yaml'
- task: PythonScript#0
inputs:
scriptSource: 'filePath'
scriptPath: "$(System.DefaultWorkingDirectory)/modify-config.py"
arguments: --svc ${{parameters.service}}_${{parameters.environment}}
#pythonInterpreter: # Optional
#workingDirectory: # Optional
#failOnStderr: false # Optional
displayName: 'Update Config files'
The modify-config.py has the following code:
#!/usr/bin/python
import os
import yaml
from jinja2 import Template
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--svc")
#parser.add_argument("--env")
args = parser.parse_args()
with open(r'./group_vars/args.svc.yaml') as file:
#value_list = yaml.load(file, Loader=yaml.FullLoader)
value_list = yaml.full_load(file)

You need to do something like this to get real directory path
See: Get parent of current directory from Python script
import os
import yaml
from jinja2 import Template
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--svc")
#parser.add_argument("--env")
args = parser.parse_args()
base_dir = Path(__file__).resolve().parent
file_path = os.path.join(base_dir, "group_vars/args.svc.yaml")
with open(file_path) as file:
#value_list = yaml.load(file, Loader=yaml.FullLoader)
value_list = yaml.full_load(file)

Related

initiating python script with arguments from another script, setting argparse values programatically

i was using a python package (spotify_dl) to genereate some files. i was doing it manually through the command line:
spotify_dl -l spotify_playlist_link -o download_directory
now i want to do it from inside another python script.
i looked at the package code and found the main function, but i can't figure how to run the main function with arguments of my choosing - in python.
for example what i want:
from spotify_dl import spotify_dl as sp_dl
if __name__=='__main__':
destination_dir = r'D:\some\folder\path'
playlists_url = ['url1','url2','url3',....]
for url in playlists_url:
sp_dl.spotify_dl(l=url,o=destination_dir)
for better clarity, here is the actual code of the spotify_dl main function:
#!/usr/bin/env python
import argparse
import json
import os
import sys
from logging import DEBUG
from pathlib import Path, PurePath
import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
from spotify_dl.constants import VERSION
from spotify_dl.models import db, Song
from spotify_dl.scaffold import log, check_for_tokens
from spotify_dl.spotify import fetch_tracks, parse_spotify_url, validate_spotify_url, get_item_name
from spotify_dl.youtube import download_songs, default_filename, playlist_num_filename
def spotify_dl():
"""Main entry point of the script."""
parser = argparse.ArgumentParser(prog='spotify_dl')
parser.add_argument('-l', '--url', action="store",
help="Spotify Playlist link URL", type=str, required=True)
parser.add_argument('-o', '--output', type=str, action='store',
help='Specify download directory.', required=True)
parser.add_argument('-d', '--download', action='store_true',
help='Download using youtube-dl', default=True)
parser.add_argument('-f', '--format_str', type=str, action='store',
help='Specify youtube-dl format string.',
default='bestaudio/best')
parser.add_argument('-k', '--keep_playlist_order', default=False,
action='store_true',
help='Whether to keep original playlist ordering or not.')
parser.add_argument('-m', '--skip_mp3', action='store_true',
help='Don\'t convert downloaded songs to mp3')
parser.add_argument('-s', '--scrape', action="store",
help="Use HTML Scraper for YouTube Search", default=True)
parser.add_argument('-V', '--verbose', action='store_true',
help='Show more information on what''s happening.')
parser.add_argument('-v', '--version', action='store_true',
help='Shows current version of the program')
args = parser.parse_args()
if args.version:
print("spotify_dl v{}".format(VERSION))
exit(0)
db.connect()
db.create_tables([Song])
if os.path.isfile(os.path.expanduser('~/.spotify_dl_settings')):
with open(os.path.expanduser('~/.spotify_dl_settings')) as file:
config = json.loads(file.read())
for key, value in config.items():
if value and (value.lower() == 'true' or value.lower() == 't'):
setattr(args, key, True)
else:
setattr(args, key, value)
if args.verbose:
log.setLevel(DEBUG)
log.info('Starting spotify_dl')
log.debug('Setting debug mode on spotify_dl')
if not check_for_tokens():
exit(1)
sp = spotipy.Spotify(auth_manager=SpotifyClientCredentials())
log.debug('Arguments: {}'.format(args))
if args.url:
valid_item = validate_spotify_url(args.url)
if not valid_item:
sys.exit(1)
if args.output:
item_type, item_id = parse_spotify_url(args.url)
directory_name = get_item_name(sp, item_type, item_id)
save_path = Path(PurePath.joinpath(Path(args.output), Path(directory_name)))
save_path.mkdir(parents=True, exist_ok=True)
log.info("Saving songs to: {}".format(directory_name))
songs = fetch_tracks(sp, item_type, args.url)
if args.download is True:
file_name_f = default_filename
if args.keep_playlist_order:
file_name_f = playlist_num_filename
download_songs(songs, save_path, args.format_str, args.skip_mp3, args.keep_playlist_order, file_name_f)
if __name__ == '__main__':
spotify_dl()
so far i could see mentions of sys.argv but also some comments spoke against using that.
what i want is a clear method that i could run in a loop without complications.
spotify_dl is badly designed, I commonly use this:
def parse_args(argv=None):
parser = argparse.ArgumentParser()
...
return parser.parse_args(argv)
def main(args):
# run your code
if __name__ == "__main__":
args = parse_args()
main(args)
Then you can import this first script in another and call the main function:
from my_first_script import main
def a_function():
args = namedtuple("args", ("arg1", ...))("value1")
main(args)
But you can workaround by overriding sys.argv:
if __name__=='__main__':
destination_dir = r'D:\some\folder\path'
playlists_url = ['url1','url2','url3',....]
for url in playlists_url:
sys.argv = [sys.executable, "-o", destination_dir, "-l", url]
sp_dl.spotify_dl()
You can use subprocess here.
I did not try your example because I don't have those libraries installed, but here's a simple example.
First, a simple commandline script called testpy.py has the following:
import sys
import argparse
def check_arg(args=None):
parser = argparse.ArgumentParser(prog='Test',
description='Test',
epilog='Test')
parser.add_argument('-f', '--first',
help='First argument',
required='True')
results = parser.parse_args(args)
return (results.first)
def main():
with open('test.txt', 'a') as file:
file.write('Success, {}\n'.format(f))
if __name__ == '__main__':
f = check_arg(sys.argv[1:])
main()
This takes one argument f and exports a text file (test.txt) with whatever argument was supplied.
This script can be run from a next script as (save this as new script file):
from subprocess import run, PIPE
args = ['python3', 'testpy.py', '-f', 'First input argument text']
res = run(args, stdout=PIPE, stderr=PIPE)
If you run this, you'll see that the file test.txt will be exported and calling the script testpy.py from this script was successful.

python module called with cat and command line arguments parser

cat hello.txt | python main.py foobar
what is the reason of using cat here?
I understand foobar is command line argument so I need to handle it with arguments parser. how to handle it if i do not specify parameter e.g. --parameters ?
what about hello.txt used after cat?
is it the name of the file that i am passing into python main.py call as other argument or am I dumping python main.py execution results into hello.txt? how and what exactly? am I catching what python main.py is printing with cat and writing it into hello.txt?
EDIT:
Am i capturing it correct?
import argparse
import sys
def parse_arguments():
parser = argparse.ArgumentParser()
parser.add_argument('a', nargs='*')
args, unknown = parser.parse_known_args()
return args
file_content = data = sys.stdin.read()
params = parse_arguments()
print(file_content)
print(params)

Use of argparse in Snakemake script

Is it possible to pass custom command line arguments to snakemake scripts? I have tried, but executing Snakefile with argparse results in error snakemake: error: unrecognized arguments: -zz. Below is an example script.
import argparse
def get_args():
parser = argparse.ArgumentParser(description='Compares Illumina and 10x VCFs using RTG vcfeval')
# required main arguments
parser.add_argument('-zz', metavar='--filename', dest='fn', help='Filename', required=True)
# parse arguments
args = parser.parse_args()
fn = args.fn
return fn
fn = get_args()
rule test_1:
input:
fn + "/example.txt"
shell:
"echo Using file {input}"
Passing arguments from command line is possible using --config. For example:
snakemake --config zz="filename"
In snakefile script, this can be used in this way:
rule test_1:
input:
fn + config['zz']
shell:
"echo Using file {input}"
See the doc for more info.

Unable to get the value of a command argument using argparse

I'm trying to parse the command line arguments in a very simple way:
$ python main.py --path /home/me/123
or
$ python main.py --path=/home/me/123
And then:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--path')
args = parser.parse_args()
And args returns nothings:
(Pdb) args
(Pdb) args.path
How can I access the value of --path?
You can print args.path and it will show your line argument. For more details you can check the below link for more details about argparse
Argparse Tutorial
You can also use sys to parse your command line arguments, such as
>>> import sys
>>> path = sys.argv[1] # sys.argv always start at 1
>>> print path
Check the below link for more details.
Python Command Line Arguments
Hope it helps.
It works fine for me...
>>> args
Namespace(path='/home/me/123')
So you can access it via args.path

Take string argument from command line?

I need to take an optional argument when running my Python script:
python3 myprogram.py afile.json
or
python3 myprogram.py
This is what I've been trying:
filename = 0
parser = argparse.ArgumentParser(description='Create Configuration')
parser.add_argument('filename', type=str,
help='optional filename')
if filename is not 0:
json_data = open(filename).read()
else:
json_data = open('defaultFile.json').read()
I was hoping to have the filename stored in my variable called "filename" if it was provided. Obviously this isn't working. Any advice?
Please read the tutorial carefully. http://docs.python.org/howto/argparse.html
i believe you need to actually parse the arguments:
parser = argparse.ArgumentParser()
args = parser.parse_args()
then filename will be come available args.filename
Check sys.argv. It gives a list with the name of the script and any command line arguments.
Example script:
import sys
print sys.argv
Calling it:
> python script.py foobar baz
['script.py', 'foobar', 'baz']
If you are looking for the first parameter sys.argv[1] does the trick. More info here.
Try argparse's default parameter, its well documented.
import argparse
parser = argparse.ArgumentParser(description='Create Configuration')
parser.add_argument('--file-name', type=str, help='optional filename',
default="defaultFile.json")
args = parser.parse_args()
print(args.file_name)
Output:
$ python open.py --file-name option1
option1
$ python open.py
defaultFile.json
Alternative library:
click library for arg parsing.

Categories