Forum Archive

Simple UI to run script2 + args

iApeiron

Can anybody point me in the right direction?
I'm hoping to find a basic template or example.

I need a script1.py to run "script2.py arg1 arg2 arg3"
I'm new to Pythonista, and not sure where to start.
Thank you!

zipit

Hi,

welcome to Python(ista)! You could use exec (see here) to do what you have described. But using exec is usally considered really bad style for a reason as it WILL open the doors to purgatory at some point. Is there any reason why you could not do what you want to do with a normal module?

iApeiron

Thank you. This is a start. But I also need some way to append user input as arguments for script2.
Essentially, a GUI wrapper for a pre-existing commandline .py

omz

You could just modify sys.argv in the first script, then use runpy.run_path to run the second.

iApeiron

Thanks. I don't have anything for the first script yet. Do you have a related template or example?
Essentially I want to do something like what the module Gooey is for.

iApeiron

@omz Thank you. I think I have a start now, thanks to coming across this ex13-raw_input.py

iApeiron

@omz I've got this working based on the ex13 script

from sys import argv

script2 = argv

first_name = raw_input("What is your first name? ")

middle_name = raw_input("What is your middle name? ")

last_name = raw_input("What is your last name? ")

print "Your full name is %s %s %s." % (first_name, middle_name, last_name)

But I have not got runpy to cooperate.
And this doesn't use the 'raw_input' which I need.

Do you have a solution? Thank you for your help

ccc
import sys
import runpy

try:  # https://docs.python.org/3/whatsnew/3.0.html#builtins
    raw_input          # Python 2
except NameError:
    raw_input = input  # Python 3

script2 = sys.argv[1] if sys.argv[1:] else 'script2.py'
first_name = raw_input("What is your first name? ").strip() or 'Donald'
middle_name = raw_input("What is your middle name? ").strip() or 'J.'
last_name = raw_input("What is your last name? ").strip() or 'Trump'
fmt = "%s: Your full name is %s %s %s."
print(fmt % (sys.argv[0].split('/')[-1], first_name, middle_name, last_name))
runpy.run_path(script2, init_globals={'first_name': first_name,
                                      'middle_name': middle_name,
                                      'last_name': last_name})


"""script2.py
import sys
fmt = "{}: Your full name is {first_name} {middle_name} {last_name}."
print(fmt.format(sys.argv[0], **globals()))
"""
iApeiron

@ccc Thank you for the thoughtful answer!

I think this discussion has strayed away from my original intention.

To rephrase my original intention:
A have a command line Python script which would be used as follows "python main.py arg1 arg2 arg" and then proceeds to do and print some predefined functions.
Now, I want use a wrapper script to run main.py with the args input via a prompt, and print what main.py is doing.

Thank you for help!

ccc
import sys
import runpy

try:  # https://docs.python.org/3/whatsnew/3.0.html#builtins
    raw_input          # Python 2
except NameError:
    raw_input = input  # Python 3

script2 = sys.argv[1] if sys.argv[1:] else 'script2.py'
first_name = raw_input("What is your first name? ").strip() or 'Donald'
middle_name = raw_input("What is your middle name? ").strip() or 'J.'
last_name = raw_input("What is your last name? ").strip() or 'Trump'
fmt = "%s: Your full name is %s %s %s."
print(fmt % (sys.argv[0].split('/')[-1], first_name, middle_name, last_name))
sys.argv = ['script2.py', first_name, middle_name, last_name]
with open(sys.argv[0]) as in_file:
    exec(in_file.read())  # exec() is a security hole a mile wide and 10 miles deep!!

"""script2.py
import sys
print("{}: Your full name is {} {} {}.".format(*sys.argv))
"""
ccc

Python 3 fix also merged into upstream... https://github.com/mwarkentin/Learn-Python-The-Hard-Way/pull/2/files

zipit

Uh, I didn't know that python had a short hand syntax for conditional assignments evaluating forTrue. That is nice 👍🏻.

JonB

rich,
Are you aware that you long-press the play button for a script, it lets you define arguments? Just checking, not everyone realizes this.

another option would be to use a dialogs popup rather than raw_input

import dialogs
fields=[{'title':'First Name','type':'text'},
         {'title':'Last Name','type':'text'},
         {'title':'Age','type':'number'}]
response=dialogs.form_dialog('What is your info?',fields)
iApeiron

@JonB Thanks. I really like this dialogue box! If I can get the responses to act as args to control my second script, then I have it made!

iApeiron

@ccc Cool thanks! What should I do with the quoted code at the bottom of your post?
When I run this in Pythonista 3, I get a whole chain of traceback errors related to argparse.py.

Traceback (most recent call last):
File "/private/var/mobile/Containers/Shared/AppGroup/B27A5227-9E55-4F91-A968-A66BBB82F074/Pythonista3/Documents/Untitled_3.py", line 17, in
exec(in_file.read()) # exec() is a security hole a mile wide and 10 miles deep!!
File "", line 191, in
File "", line 92, in main
File "", line 85, in parse_args
File "/var/mobile/Containers/Bundle/Application/4C7B9AD2-D561-40E5-9F3D-40741DBE123D/Pythonista3.app/Frameworks/Py2Kit.framework/pylib/argparse.py", line 1702, in parse_args
args, argv = self.parse_known_args(args, namespace)
File "/var/mobile/Containers/Bundle/Application/4C7B9AD2-D561-40E5-9F3D-40741DBE123D/Pythonista3.app/Frameworks/Py2Kit.framework/pylib/argparse.py", line 1734, in parse_known_args
namespace, args = self._parse_known_args(args, namespace)
File "/var/mobile/Containers/Bundle/Application/4C7B9AD2-D561-40E5-9F3D-40741DBE123D/Pythonista3.app/Frameworks/Py2Kit.framework/pylib/argparse.py", line 1943, in _parse_known_args
stop_index = consume_positionals(start_index)
File "/var/mobile/Containers/Bundle/Application/4C7B9AD2-D561-40E5-9F3D-40741DBE123D/Pythonista3.app/Frameworks/Py2Kit.framework/pylib/argparse.py", line 1899, in consume_positionals
take_action(action, args)
File "/var/mobile/Containers/Bundle/Application/4C7B9AD2-D561-40E5-9F3D-40741DBE123D/Pythonista3.app/Frameworks/Py2Kit.framework/pylib/argparse.py", line 1792, in take_action
argument_values = self._get_values(action, argument_strings)
File "/var/mobile/Containers/Bundle/Application/4C7B9AD2-D561-40E5-9F3D-40741DBE123D/Pythonista3.app/Frameworks/Py2Kit.framework/pylib/argparse.py", line 2205, in _get_values
arg_strings.remove('--')
AttributeError: 'tuple' object has no attribute 'remove'

ccc

Put that text at the end into a file called script2.py ;-). Then run the rest of the code in a separate file that I called script1.py.

iApeiron

@ccc Thanks. I still get the traceback error "AttributeError: 'tuple' object has no attribute 'remove'"

ccc

Try changing this line:

sys.argv = ['script2.py', first_name, middle_name, last_name]

To have square brackets [] instead of parentheses ().

https://github.com/cclauss/runpy_hack

iApeiron

@ccc You're right! It works! Thank you for your help!

iApeiron

@ccc Thank you! This works as expected!
The first two args are necessary, the third arg is supposed to be optional. In its current form, (with Trump removed of course,) leaving the third arg blank causes script2 error (citing an invalid arg).
Do you know how to leave an arg as optional?

ccc

The part about 'Trump' being removed made my day! Thanks for that.

# in script2.py, select one of the following and rename it to main()

def default_arg_main(script_name, first_name, middle_name, last_name=''):
    last_name = last_name or 'Bonehead'
    fmt = "{}: Your full name is {} {} {}."
    print(fmt.format(script_name, first_name, middle_name, last_name))

def if_main(*args):
    if len(args) == 4:
        fmt = "{}: Your full name is {} {} {}."
    else:
        fmt = "{}: Your full name is {} {}."
    print(fmt.format(*args))

def join_main(*args):
    print("{}: Your full name is {}.".format(args[0], ' '.join(args[1:])))

def list_main(*args):
    fmt = ('Zero sys.argv is not possible!',
           'Usage: {} first_name, [middle_name, [last_name]]',
           "{}: Your full name is {}.",
           "{}: Your full name is {} {}.",
           "{}: Your full name is {} {} {}.")[len(args)]
    print(fmt.format(*args))

# and then...
print('=' * 44)
main(*sys.argv)
iApeiron

Clearly, you are a Python master!

iApeiron

@ccc Here is the project: Savethemblobs_app
What improvements would you make? Please feel free to fork.