I'm working on cloning a Virtual Machine (VM) in vCenter environment using this code. It takes command line arguments for name of the VM, template, datastore, etc. (e.g. $ clone_vm.py -s <host_name> -p < password > -nossl ....)
I have another Python file where I've been able to list the Datastore volumes in descending order of free_storage. I have stored the datastore with maximum available storage in a variable ds_max. (Let's call this ds_info.py)
I would like to use ds_max variable from ds_info.py as a command line argument for datastore command line argument in clone_vm.py.
I tried importing the os module in ds_info.py and running os.system(python clone_vm.py ....arguments...) but it did not take the ds_max variable as an argument.
I'm new to coding and am not confident to change the clone_vm.py to take in the Datastore with maximum free storage.
Thank you for taking the time to read through this.
I suspect there is something wrong in your os.system call, but you don't provide it, so I can't check.
Generally it is a good idea to use the current paradigm, and the received wisdom (TM) is that we use subprocess. See the docs, but the basic pattern is:
from subprocess import run
cmd = ["mycmd", "--arg1", "--arg2", "val_for_arg2"]
run(cmd)
Since this is just a list, you can easily drop arguments into it:
var = "hello"
cmd = ["echo", var]
run(cmd)
However, if your other command is in fact a python script it is more normal to refactor your script so that the main functionality is wrapped in a function, called main by convention:
# script 2
...
def main(arg1, arg2, arg3):
do_the_work
if __name__ == "__main__":
args = get_sys_args() # dummy fn
main(*args)
Then you can simply import script2 from script1 and run the code directly:
# script 1
from script2 import main
args = get_args() # dummy fn
main(*args)
This is 'better' as it doesn't involve spawning a whole new python process just to run python code, and it generally results in neater code. But nothing stops you calling a python script the same way you'd call anything else.
I have a cronjob which executes a python script. python script takes two parameter username and pass.
for example : execute.py vijay hTbY87
Requirement is to take this username and pass from dataBag i have in chef.
My instance where i need to run this cronjob is in AWS.
Is there a way to have such a cronjob ?
So assuming you're using the built-in cron resource (you might want to use the cron_d resource instead, there are some subtle differences), it's all just writing the Ruby code you want:
params = data_bag_item('bagname', 'itemname')
cron 'myscript' do
command "python /path/to/execute.py #{params['user']} #{params['password']}"
# Other properties here to set the schedule.
# ...
end
Create a cronrun.sh file that contains the following:
#!/usr/bin/env bash
crontab <<EOF
*/30 * * * * /path/to/execute.py vijay hTbY87 > /path/to/logs/output.log 2>&1
EOF
This would execute every 30 minutes and will pipe the output (or Error message) to a logs directory. To search for another time interval, Google crontab.guru every ___ minutes or hours or days or whatever you want.
Make sure that you type chmod +x cronrush.sh so that the file becomes executable.
As a personal project to improve my python skills I created a script that retrieves weather data. It takes multiple command line arguments to specify the location and what specific information is wanted.
I'd like to make a second file to run it with specific command line arguments using a double click. I already learned how to make it into an executable/make a second file execute it. However, I don't know how to run it with command line arguments.
Currently my secondary file (wrapper?.. unsure of terminology) looks like this:
#! /usr/bin/env python
import weather
weather.main()
This runs but I don't know how to create command line arguments for it without running from the shell. I'd like to have a simple executable to run the weather for where I am quickly.
Well, you can call a shell process using the os.system or the subprocess module.
os.system takes a string and passes it as a command to a shell.
import os
os.system("ls -1")
Whereas subprocess takes a list of all the arguments (the program itself being the first argument) and passes it as a command.
import subprocess
# Simple command
subprocess.call(['ls', '-1'], shell=True)
Seeing these examples, it's easy to tell that you want the executable program to call either one of these (os.system or subprocess). I recommend using the latter, as it offers more variety.
If you want more information, I suggest you read the review of subprocess on Python Module of the Week..
Add to your wrapper script:
import sys
sys.argv[1:] = ['what', 'ever', 'u', 'want']
before the call to weather.main().
Is it possible to call a script from the command prompt in windows (or bash in linux) to open Maya and then subsequently run a custom script (possibly changing each time its run) inside Maya? I am searching for something a bit more elegant than changing the userSetup file and then running Maya.
The goal here is to be able to open a .mb file, run a script to position the scene inside, setup a generic set of lights and then render the scene to a specific place and file type. I want to be able to set this up as a scheduled task to check for any new scene files in a directory and then open maya and go.
Thanks for the help!
For something like this you can use Maya standalone instead of the full blown UI mode. It is faster. It is ideal for batch scheduled jobs like these. Maya standalone is just Maya running without the GUI. Once you have initialized your Maya standalone, you can import and call any scripts you want, as part of the original calling script. To start you off here is an example: (Feel free to use this as a reference/modify it to meet your needs)
In your script you first initialize Maya standalone.
import maya.standalone
maya.standalone.initialize("Python")
import maya.cmds as cmds
cmds.loadPlugin("Mayatomr") # Load all plugins you might need
That will get Maya running. Now we open and/or import all the files necessary (egs. lights, models etc.)
# full path to your Maya file to OPEN
maya_file_to_open = r"C:/Where/Ever/Your/Maya_Scene_Files/Are/your_main_maya_file.mb"
# Open your file
opened_file = cmds.file(maya_file_to_open, o=True)
# full path to your Maya file to IMPORT
maya_file_to_import = r"C:/Where/Ever/Your/Maya_Scene_Files/Are/your_maya_file.mb"
# Have a namespace if you want (recommended)
namespace = "SomeNamespaceThatIsNotAnnoying"
# Import the file. the variable "nodes" will hold the names of all nodes imported, just in case.
nodes = cmds.file(maya_file_to_import, i=True,
renameAll=True,
mergeNamespacesOnClash=False,
namespace=namespace,
returnNewNodes=True,
options="v=0;",
type="mayaBinary" # any file type you want. this is just an example.
)
#TODO: Do all your scene setup/ positioning etc. if needed here...
#Tip: you can use cmds.viewFit(cam_name, fitFactor=1) to fit your camera on to selected objects
Now we save this file out and call Maya Batch renderer to render it out
render_file = "C:/Where/Ever/Your/Maya_Scene_Files/Are/your_RENDER_file.mb"
cmds.file(rename=render_file)
cmds.file(force=True, save=True, options='v=1;p=17', type='mayaBinary')
import sys
from os import path
from subprocess import Popen
render_project = r"C:/Where/Ever/YourRenderProjectFolder"
renderer_folder = path.split(sys.executable)[0]
renderer_exec_name = "Render"
params = [renderer_exec_name]
params += ['-percentRes', '75']
params += ['-alpha', '0']
params += ['-proj', render_project]
params += ['-r', 'mr']
params += [render_file]
p = Popen(params, cwd=renderer_folder)
stdout, stderr = p.communicate()
That's it! Of Course, your script will have to be run using Maya's Python interpreter (Mayapy).
Do check out the docs for all the commands used for more options, esp.:
cmds.file()
cmds.viewFit()
cmds.loadPlugin()
Subprocess and Popen
PLUS, because of the awesomeness of Python, you can use modules like sched (docs) to schedule the running of this method in your Python code.
Hope this was useful. Have fun with this. Cheers.
A lot depends on what you need to do.
If you want to run a script that has access to Maya functionality, you can run a Maya standalone instance as in Kartik's answer. The mayapy binary installed in the same folder as your maya is the Maya python interpreter, you can run it directly the same way you'd run python.exe Mayapy has the same command flags as a regular python interpreter.
Inside a mayapy session, once you call standalone.initialize() you will have a running Maya session - with a few exceptions, it is as if you were running inside a script tab in a regular maya session.
To force Maya to run a particular script on startup, you can call the -c flag, just the way you would in python. For example, you can start up a maya and print out the contents of an empty scene like this (note: I'm assuming mayapy.exe is on your path. You can just CD to the maya bin directory too).
mayapy -c 'import maya.standalone; maya.standalone.initialize(); import maya.cmds as cmds; print cmds.ls()'
>>> [u'time1', u'sequenceManager1', u'renderPartition', u'renderGlobalsList1', u'defaultLightList1', u'defaultShaderList1', u'postProcessList1', u'defaultRenderUtilityList1', u'defaultRenderingList1', u'lightList1', u'defaultTextureList1', u'lambert1', u'particleCloud1', u'initialShadingGroup', u'initialParticleSE', u'initialMaterialInfo', u'shaderGlow1', u'dof1', u'defaultRenderGlobals', u'defaultRenderQuality', u'defaultResolution', u'defaultLightSet', u'defaultObjectSet', u'defaultViewColorManager', u'hardwareRenderGlobals', u'hardwareRenderingGlobals', u'characterPartition', u'defaultHardwareRenderGlobals', u'lightLinker1', u'persp', u'perspShape', u'top', u'topShape', u'front', u'frontShape', u'side', u'sideShape', u'hyperGraphInfo', u'hyperGraphLayout', u'globalCacheControl', u'brush1', u'strokeGlobals', u'ikSystem', u'layerManager', u'defaultLayer', u'renderLayerManager', u'defaultRenderLayer']
You can run mayapy interactively - effectively a command line version of maya - using the -i flag: This will start mayapy and give you a command prompt:
mayapy -i -c \"import maya.standalone; maya.standalone.initialize()\""
which again starts the standalone for you but keeps the session going instead of running a command and quitting.
To run a script file, just pass in the file as an argument. In that case you'd want to do as Kartik suggests and include the standalone.initalize() in the script. Then call it with
mayapy path/to/script.py
To suppress the userSetup, you can create an environmnet variable called MAYA_SKIP_USERSETUP_PY and set it to a non-zero value, that will load maya without running usersetup. You can also change environment varialbes or path variables before running the mayap; for example I can run mayapys from two different environments with these two bash aliases (in windows you'd use SET instead of EXPORT to change the env vars):
alias mp_zip="export MAYA_DEV=;mayapy -i -c \"import maya.standalone; maya.standalone.initialize()\""
alias mp_std="export MAYA_DEV=C:/UL/tools/python/ulmaya;export ZOMBUILD='C:/ul/tools/python/dist/ulmaya.zip';mayapy -i -c \"import maya.standalone; maya.standalone.initialize()\""
This blog post includes a python module for spinning up Mayapy instances with different environments as needed.
If you want to interact with a running maya from another envrionment - say, if you're trying to remote control it from a handheld device or a C program - you can use the Maya commandPort to handle simple requests via TCP. For more complex situations you could set up a basic remoting service like this of your own, or use a pre-exiating python RPC module like RPyC or ZeroMQ
I have a jython server script (called rajant_server.py) that interacts with a java api file to communicate over special network radios. I have a python program which acts as a client (and does several other things as well). Currently, I have to start the server first by opening a command/terminal window and typing:
cd [path to directory containing rajant_server.py
jython rajant_server.py
Once the server successfully connects it waits for the client, which I start by running:
cd [path to directory containing python client program]
python main.py
When the client connects, the server prints out information (currently for debug) in it's command/terminal window, and the client program prints out debug information in it's command/terminal window. What I want to do is do away with the complex process by calling jython from my 'main.py' program using the subprocess module.
The problem is two fold:
1 - I need the rajant_server.py program to open in it's own terminal/command window
2 - jython needs to be run in the directory where the rajant_server.py file is stored, in other words, typing the following into the command/Terminal Window doesn't work (don't ask me why):
jython C:/code_dir/comm/server/rajant_server.py
but:
cd C:/code_dir/comm/server
jython rajant_server.py
does work.
Okay... I just got something to work. It seems like a bit of a hack, so I would still love ideas on a better approach. Here is what I am currently doing:
serverfile = r'rajant_server_v2.py'
serverpath = os.path.join(os.path.realpath('.'),'Comm',serverfile)
serverpath = os.path.normpath(serverpath)
[path,file] = os.path.split(serverpath)
command = '/C jython '+file+'\n'
savedir = os.getcwd()
os.chdir(path)
rajantserver = subprocess.Popen(["cmd",command],\
creationflags = subprocess.CREATE_NEW_CONSOLE)
#Change Directory back
os.chdir(savedir)
#Start Client
rajant = rajant_comm.rajant_comm()
rajant.start()
If you have a solution that will work in both linux & windows you would be my hero. For some reason I couldn't change the stdin or stdout specifications on the subprocess when I added creationflags = subprocess.CREATE_NEW_CONSOLE.
The Popen function in subprocess accepts an optional parameter 'cwd', to define the current working directory of the child process.
rajantserver = subprocess.Popen(["cmd",command],\
creationflags = subprocess.CREATE_NEW_CONSOLE,\
cwd = path)
You can get rid of the os.getcwd call and the two os.chdir calls this way. If you want to be able to use this script on Linux, you have to do without 'cmd'. So call Popen with ["jython", file] as first argument.
EDIT: I've just seen that CREATE_NEW_CONSOLE is not defined in the subprocess module when running on Linux. Use this:
creationflags = getattr(subprocess,"CREATE_NEW_CONSOLE",0),\
This will be the same as before, except it falls back to the default value 0 when the subprocess module does not define CREATE_NEW_CONSOLE.