1

I am writing some code in Python that is almost working, but there is one thing I am unable to figure out.

I need to loop through 2 lists. I want to loop through until the first list is complete; whereas the second list should repeat itself until the first list is complete.

I want to input a list of databases and a list of streams. Then I want the code to output the 9 lines by replacing where it has "+ stream +" and "+ item +". The item part works fine, but I don't know how to output the list of streams while iterating through the list of databases. I want the streams to cycle through and then repeat. So it will start at 1a and then reach 3c, and then start over again at 1a. I want this to happen until it reaches the last database in the list.

databases=input("Enter databases: ") streams="1a 2a 3a 1b 2b 3b 1c 2c 3c" stream="1a" db_list = databases.split() streams_list= streams.split() for item in db_list: print("unlink $ORACLE_BASE/admin/" + item + "/backup") print("unlink $ORACLE_BASE/admin/" + item + "/dpdump") print("unlink $ORACLE_BASE/admin/" + item + "/exp") print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/backup") print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/dpdump") print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/exp") print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/backup $ORACLE_BASE/admin/" + item + "/backup") print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/dpdump $ORACLE_BASE/admin/" + item + "/dpdump") print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/exp $ORACLE_BASE/admin/" + item + "/exp") 

Here is the output:

Enter databases: database1 database2 database3 unlink $ORACLE_BASE/admin/database1/backup unlink $ORACLE_BASE/admin/database1/dpdump unlink $ORACLE_BASE/admin/database1/exp mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database1/backup mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database1/dpdump mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database1/exp ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database1/backup $ORACLE_BASE/admin/database1/backup ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database1/dpdump $ORACLE_BASE/admin/database1/dpdump ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database1/exp $ORACLE_BASE/admin/database1/exp unlink $ORACLE_BASE/admin/database2/backup unlink $ORACLE_BASE/admin/database2/dpdump unlink $ORACLE_BASE/admin/database2/exp mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database2/backup mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database2/dpdump mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database2/exp ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database2/backup $ORACLE_BASE/admin/database2/backup ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database2/dpdump $ORACLE_BASE/admin/database2/dpdump ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database2/exp $ORACLE_BASE/admin/database2/exp unlink $ORACLE_BASE/admin/database3/backup unlink $ORACLE_BASE/admin/database3/dpdump unlink $ORACLE_BASE/admin/database3/exp mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database3/backup mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database3/dpdump mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database3/exp ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database3/backup $ORACLE_BASE/admin/database3/backup ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database3/dpdump $ORACLE_BASE/admin/database3/dpdump ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database3/exp $ORACLE_BASE/admin/database3/exp 

My output has STREAM1a every time, but I want it to cycle through the pattern of 1a, 2a, 3a, 1b, 2b, 3b, 1c, 2c, and 3c. As mentioned, if I have more than 9 databases, then it would start over at 1a again. How can I achieve this?

The only part of my code that isn't working the way I want is where it says "+ stream +".

3
  • do you want it to cycle through all the streams for each item in db_list? For example, database1 1a, database1 2a, database1 3a, etc.? Commented May 8, 2014 at 22:39
  • Yes that's exactly what I want. When it gets to database9 it will be at 3c. When it gets to database10 it needs to go back to 1a. Commented May 8, 2014 at 22:41
  • 1
    maybe a generator function Commented May 8, 2014 at 22:41

2 Answers 2

3

You should use itertools.cycle. This will allow you to get the elements of a list in an endlessly repeating cycle. Add this code at the start of your loop:

stream_cycle = itertools.cycle(streams_list) for item in db_list: stream = stream_cycle.next() 

or as @HughBothwell suggested, you can use zip and include it in the definition of the for loop:

for item, stream in zip(db_list, itertools.cycle(streams_list)): 

Either way will give you the next stream at each iteration of the loop. If you have more dbs than streams, then it will repeat.

Sign up to request clarification or add additional context in comments.

6 Comments

... or for item,stream in zip(db_list, itertools.cycle(stream)):
Good suggestion. I've added that in.
I'm getting the error: ImportError: cannot import name 'izip' <-- Is that because I'm using Python 3?
@user2554129 Yes, izip doesn't exist in Python 3. That's why I used zip in my example rather than izip. You don't need to import it, either.
That worked perfectly! Thank you! :) Is there a way for me to share my completed code in case anyone is interested?
|
2

The trick is to use iterator from itertools called cycle

from itertools import cycle databases=input("Enter databases: ") streams="1a 2a 3a 1b 2b 3b 1c 2c 3c" stream="1a" db_list = databases.split() stream_list= streams.split() for item, stream in zip(db_list, cycle(stream_list)): print("unlink $ORACLE_BASE/admin/" + item + "/backup") print("unlink $ORACLE_BASE/admin/" + item + "/dpdump") print("unlink $ORACLE_BASE/admin/" + item + "/exp") print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/backup") print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/dpdump") print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/exp") print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/backup $ORACLE_BASE/admin/" + item + "/backup") print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/dpdump $ORACLE_BASE/admin/" + item + "/dpdump") print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/exp $ORACLE_BASE/admin/" + item + "/exp") 

bonus - command line parameters parsing using docopt

Small bonus: to let you call the script and conveniently enter paremeters from command line

Install docopt package (just once)

$ pip install docopt 

Write modifed version of the script db.py:

"""Usage: db.py -s <stream> (-s <stream>)... <db> <db>... db.py -h For all database names <db> generates commands combining it with names of <stream>s. """ from docopt import docopt from itertools import cycle args = docopt(__doc__) db_list = args["<db>"] stream_list = args["<stream>"] for item, stream in zip(db_list, cycle(stream_list)): print("unlink $ORACLE_BASE/admin/" + item + "/backup") print("unlink $ORACLE_BASE/admin/" + item + "/dpdump") print("unlink $ORACLE_BASE/admin/" + item + "/exp") print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/backup") print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/dpdump") print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/exp") print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/backup $ORACLE_BASE/admin/" + item + "/backup") print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/dpdump $ORACLE_BASE/admin/" + item + "/dpdump") print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/exp $ORACLE_BASE/admin/" + item + "/exp") 

Printout usage string:

$ python db.py Usage: db.py -s <stream> (-s <stream>)... <db> <db>... db.py -h 

Show some help string:

$ python db.py -h Usage: db.py -s <stream> (-s <stream>)... <db> <db>... db.py -h For all database names <db> generates commands combining it with names of <stream>s. 

And call it for real use:

$ python db.py -s s2 -s s2 db1 db2 db3 unlink $ORACLE_BASE/admin/db1/backup unlink $ORACLE_BASE/admin/db1/dpdump unlink $ORACLE_BASE/admin/db1/exp mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db1/backup mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db1/dpdump mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db1/exp ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db1/backup $ORACLE_BASE/admin/db1/backup ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db1/dpdump $ORACLE_BASE/admin/db1/dpdump ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db1/exp $ORACLE_BASE/admin/db1/exp unlink $ORACLE_BASE/admin/db2/backup unlink $ORACLE_BASE/admin/db2/dpdump unlink $ORACLE_BASE/admin/db2/exp mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db2/backup mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db2/dpdump mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db2/exp ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db2/backup $ORACLE_BASE/admin/db2/backup ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db2/dpdump $ORACLE_BASE/admin/db2/dpdump ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db2/exp $ORACLE_BASE/admin/db2/exp unlink $ORACLE_BASE/admin/db3/backup unlink $ORACLE_BASE/admin/db3/dpdump unlink $ORACLE_BASE/admin/db3/exp mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db3/backup mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db3/dpdump mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db3/exp ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db3/backup $ORACLE_BASE/admin/db3/backup ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db3/dpdump $ORACLE_BASE/admin/db3/dpdump ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db3/exp $ORACLE_BASE/admin/db3/exp 

3 Comments

I placed "import itertools" at the top, then I put "from itertools import cycle, izip" in. I changed my for loop to "for item, stream in zip(db_list, itertools.cycle(streams_list)):", but I'm getting this error: "ImportError: cannot import name 'izip'". I think this is because I'm using Python 3?
Jan,That seems pretty cool! Unfortunately I won't be able to take advantage of it since I will be working on hundreds of different servers. I'm not even sure if the servers have Python. So I will probably need to run the code on my local machine.
@user2554129 This sounds scary - no Python - no fun. If you care about minimal installation dependencies, then since Python 2.7 there is builtin argparse module. But it seems wiser to generate the scripts on your machine and distribute it to the servers (over ssh?). But I am getting off track now. Good luck.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.