(Newbie) Calling other programs under Pythonista
I tried to call programs I wrote so that I can have a higher level of python program running a main loop. Then depend upon user input, I would run one of these smaller programs and then return to the main loop for users to choose other programs to run.
For example, my program can call all the game programs in pythonista and let user choose which one to play.
In this regards, I saw sample for calling class module, e.g. there is a sample of dropboxlogin and you can use that kind in dropboxsync like this:
... import dropboxlogin ... x = dropboxlogin.get_client() ... state_download_all(x) # i.e. one can use dropboxlogin as class to produce objects and manipulate them
My question in this situation is how to use dropboxlogin as a program not as class and also how to structure dropboxlogin so that it can be called as a program.
To use Cards.py as an example instead of dropboxlogin (too risky to test), which I have tried a bit. The result is not as expected:
a) calling Cards.py itself
import Cards Cards
result: the Cards program would run after I exit the program
b) calling Cards as a class
import Cards x=Cards.Game()
result: same as above
import Cards run(Cards.Game())
result: the game run immediately but when I exit the Cards game, the main python crashed and pythonista point to the line "run(Cards.Game())" and said "NameError: name 'run' is not defined
My question is
a) Is there anyway to call Cards.
b) Some of the sample module use run(Cards.Game()), some used if name == 'main" and some have nothing. Can you tell what should I use for developing these independent program for calling by others. In other words, is the Cards program having run(Cards.Game()) is the problem
Another question unrelated to above is that one of the small program would like to play a MP3 (in the background) and display a few photos. Is there anyway to call and play MP3 (even if I download that into my directory, if calling itune is too hard)
Sorry for such newbie questions.
For all your assistance and kind advice.
Your questions are really good ones. Part of the problem that you face is that Python is far more flexible than other languages. C, Java, etc. force programs to have a main() function as their single entry point but scripting languages like Python allow for more freedom. As you have said, sometimes you will have a single function to call and other times you must execute many lines.
The general approach would be to:
- import the file that you want to run
- take all lines in the file that you want to run EXCEPT
a) lines starting with 'import' and 'from'
b) lines starting with 'class' and 'def' as well as the lines indented under them
c) remove: if name == 'main': and dedent all text to the right of or indented below this text (while continuing to observe 2a and 2b).<br>
- execute the lines gathered in 2) in an eval() function call
- you may want to surround the eval call with a try catch block of the form:
import Cards try: run(Cards) except NameError: pass
Of course, it is vital that step 2) is done with a full understanding of comments (#) plus the four kinds of string quoting allowed in Python: ', ", ''', and """
If you have a limited number of programs that you run in this way, instead of writing and debugging all that code, my recommendation is that you edit by hand each program to have a consistent entry point:
def main(argv): pass # <-- your program logic goes here if __name__ == '__main__": main(sys.argv)
Then you can put the program logic in place of 'pass' and your mainmenu program can run all programs with a common syntax.
The other thing that you observed is that Pythonista Scenes have a strange behavior in that they only really run once your script has terminated as discussed in: http://omz-software.com/pythonista/forums/discussion/169/correct-way-to-do-threading-in-pythonista#Item_10
I think your mp3 question is answered in http://omz-software.com/pythonista/forums/discussion/191/sounds-fonts/p1
Thanks. After that post, I kept on trying for the night and very happy indeed to see your post. It seems it would be another day to test and understand. May be this weekend.
Reading a bit the other links, the key I think is (a) one can do text based game, play some music etc. but not involve Scene and (b) if Scene is involved, one has to incorporate all these into the high level program I am doing (with may be a bit offload to other helper class module outside). That might the ultimate strategy I would opt for.
Thanks once again.
One more pointer... @Sebastian contributed a <b>class MultiScene (Scene)</b> which enables multiple scenes to run in a single Pythonista app. This is used in a game that he called an Impossiball Clone. See http://omz-software.com/pythonista/forums/discussion/648/impossiball-clone/p1
More to learn and more to test this weekend ... great!
Have to hand in my assignment deadline to coursera on Beethoven 32 sonata. Would struggle to fit these two things together but I would try.
Thanks very much. really thanks.
BTW, to be honest, (1) I still do not get the paradigm of run(classx(..)) . It is a paradigm I do not get. (2) Script paradigm use main (as in c). (3) Object-class pardigm use class definition (which import) or dynamic object (as in objective c; or mention lisp/scheme way) and then create object using this class factory. (3) Even the eval (in python or in lisp macro) paradigm, I can get it to share code using dynamic generation and execution.
But what is run(classx(..))
Is it just a python interpret special function, a macro expander, ... sorry week end problem.
run()in question is really
scene.run()-- it is Pythonista scene specific and not really what you want for your general approach. Several Pythonista sample apps have the line
'from scene import *'which simplifies coding and readability. However the import * syntax runs counter to warnings in http://docs.python.org/release/2.7/howto/doanddont.html
To prove to yourself that it is really
scene.run()getting called, edit Cards.py and comment out the line
from scene import *and put in the line
import scene. Now run Cards and add
'scene.'in all places where errors pop up (e.g.
scene.run, etc.). Now your mainmenu app should complain that
run()is not defined.
I discovered a huge optimization to the general approach that I outlined in my first post in this thread:
- read in the full text of the program you want to run
- strip out all comments and quoted strings
if not '__name__' in program_text: import program
In reality, all you need to do to run Cards or Clock is import them because they do not have the
__name__technique of conditionally executing code. The call to
run()is useless if you have already imported these modules.
import Cards # this one line will run Cards import Clock # this one line will run Clock
If you put both of those lines in a single script, only the LAST one will actually be run. This is due to the unique characteristics of Pythonista scenes discussed in my first post in this thread. Good luck with Beethoven's 32nd.
Import ... and run! Ooh! Really need to learn python properly. Just found coursera has a course in Python (and even signature course as well).
https://www.coursera.org/course/interactivepython Post it as a seperate thread.