Using subprocess under django to call a scala program - python

I have a scala program that I would like to call from within django using subprocess:
encode_cmd = "/usr/local/share/scala/scala-2.10.0/bin/scala -cp /home/django/code/classes conn {}".format(self.id)
output = subprocess.Popen(encode_cmd, shell = True, stdout = subprocess.PIPE).stdout.read()
This code runs fine in the python shell, but when run as part of the normal webserver process it fails to find the scala dependencies (the scala class references the slick libraries for example) failing with the java.lang.NoClassDefFoundError.
I've tried specifying specific users as part of the mod_wsgi daemon process, but this makes no difference.

You should add jars in your command like that: -cp /home/django/code/classes:/path/to/slick.jar, otherwise it only includes the .class' and folders containing class files as per packages.
You can always rely on the shell expansion if you have many jars: /path/to/dependencies/*.jar
Another option is using SBT's xsbt-start-script-plugin or Maven's appassembler plugin to create a shell script

Related

Set an environment variable from a python script

I am trying to automate build, test, and deployment via CI/CD. I have a python script designed to query my git remote repository, select the most recent tag in semantic versioning format (x.x.x) and increment it depending on the type of change.
I would like to set my environment variable (GIT_NEW_VERSION) so that this can be used within my Makefile and the generated binary will have the version available. The problem with this is that the python script is run in a sub-process that doesn't have access to the parent process variables. So I can modify the variable only for the current process and any processes created after but not the process that called the python script.
I could call make from the python script but that is not ideal for error management and logging with my CI tool.
bash:
LD_LIBRARY_PATH=my_path
sqsub -np $1 /path/to/executable
Similar, in Python:
import os
import subprocess
import sys
os.environ['LD_LIBRARY_PATH'] = "my_path" # visible in this process + all children
subprocess.check_call(['sqsub', '-np', sys.argv[1], '/path/to/executable'],
env=dict(os.environ, SQSUB_VAR="visible in this subprocess"))

How would I allow others to use my script from anywhere in the shell without having to type out the file extension?

Excuse the awkward question wording.
I've made a script. I would like for others to download it from github, and run it by typing programName argument1 argument2, similar to any other popular app used through the terminal such as Jupyter or even opening Atom/Sublime/etc. (ex:jupyter notebook, atom .). However, unlike Jupyter or sublime, my script isn't launching another app, it's a small app meant to be used in the shell.
Currently, to use my script, one must type into the command line python programName.py arg1 etc from within the file's directory.
How do I allow others to dl it and use it from anywhere (not having to be within the directory), without having to type out the whole python programName.py part, and only having to type programName arg1?
This blog post explains step by step how to create a distribution that you can install and it would turn into an executable.
You can refer to this github repo for a sample application.
The full documentation of setuptools is available here.
In general, you should configure your setup.py in order to use the command in the entry-point option:
setup(
name = "your_app_name",
packages = ["package_name"],
entry_points = {
"console_scripts": ['cmd_name = package_name.package_name:main']
},
....
)
This solution would work on every OS where you have installed python.
Your script may need to have an interpreter, "shebang", besides being "reachable" by the $PATH
#!interpreter [optional-arg]
For example, you could have something like
#!/usr/bin/env python
or to force a specific version
#!/usr/local/bin/python2.7
Next, your script needs to be available within the $PATH, check this answer that covers that part: https://unix.stackexchange.com/q/29608/53084
You can simply add your script to PATH variable in order to launch it from anywhere.
In Linux distros, you can simply do it by using a bash command PATH=$PATH:/path/to/your/script.
Make sure you don't have the space around the "=" operator.
Now, the second thing is you don't want your script to be named as pythonProgram.py.You can simply remove the extension .py from PythonProgram.py by adding a single line to the starting of your script.
Open up your script and at the very begining type #!/usr/bin/python.This should be the first line of your code.This line is called shebang and is used to tell the bash which interpreter to be used for compiling the script.
If everything went right, you will be able to run your script as pythonProgram arg1.
In addition to mabe02: Python is a scripting language and usually not compiled, which means you will need an interpreter to run your program.
Programms made in C f.e. can be run on its own because they were compiled into machine code by a compiler.
An interpreter is similar to a compiler as it reads your script and interprets it at runntime. That is why you need to write python before your programm, to tell your computer to interpret your script on runntime, using python. This doesn't mean that there are no possibilities to compile python as can be seen in the other answer and in this link Can a python program be run on a computer without Python? What about C/C++? (py2exe and py2app).

Way to run Maven from Python script?

(I am using Windows.)
I am trying to run maven from a python script. I have this:
import subprocess
mvn="C:\\_home\\apache-maven-2.2.1\\bin\\mvn.bat --version"
p = subprocess.Popen(mvn, shell=True, stdout = subprocess.PIPE)
stdout, stderr = p.communicate()
print p.returncode # is 0 if success
It works fine, but I am wondering about the following:
Better ways to add parameters instead of appending the string.
Maybe some specific way to run maven without the above.
A way to show the output (currently it only prints a 1 or 0 based on failure/success).
What I am trying to accomplish long term (I note this in case someone has a better method) is to make a simple script to build a list of projects and move another list of files (jars/other modified things) to a folder to deploy to VMs, it's a huge pain to do manually. I have this working in a batch script no sweat, I am just curious to learn Python and wonder if it'd be easier to manage because I could just make a couple of lists and iterate over each of the locations rather than have a line for each task in the batch script.
(Short version of what my batch script looks like.)
#set version=7.8.3
#set staging_folder=C:\Users\me\Desktop\staging
#set stage_was=%staging_folder%\was
#set stage_ear=%stage_was%\stuffui.ear
#set stage_war=%stage_ear%\stuff-%version%.war
:: delete stage contents
call del /s /q %staging_folder%
call rmdir /s /q %stage_was%
:: make folders
call mkdir %stage_ear%
call mkdir %stage_war%\WEB-INF\lib
:: maven builds
call mvn -f C:\workspace\pom.xml -pl proj1,proj2 clean install
:: copy to stage
call xcopy C:\workspace\proj1\target\thing1.jar %stage_ear%\ /i /y
call xcopy C:\workspace\proj2\target\thing2.jar %stage_ear%\ /i /y
call xcopy C:\workspace\proj2\target\thing2.jar %stage_war%\WEB-INF\lib\ /i /y
There is the Apache Maven Invoker API.
Mark's answer to Accessing Java API information with Python mentions:
Jython which is Python run on the Java VM.
See my answers there for an example on how to use the Maven Invoker (from within Java in this particular case).
Re:
in case someone has a better method
Re:
move another list of files (jars/other modified things) to a folder
Have you considered using Maven itself (the copy-resources goal of its Resources Plugin in this particular case)?
Re:
I am just curious to learn Python
Since you are working with Java anyway: Have you considered Groovy as the scripting language of your choice?
Some of its advantages:
The Java language is a subset of the Groovy language. I.e. every Java code is also Groovy code. You don't have to use the full-fledged Groovy syntax from the beginning while learning it.
It can be scripted.
It is supported as scripting and DSL in tools like Jenkins.

create unix alias using a python3 script

Well, as we all known, creating an alias in a terminal shell is quite easy:
ZZ:~ zhangzhao$ alias c='uname'
ZZ:~ zhangzhao$ c
Darwin
ZZ:~ zhangzhao$
But now I want to do the same thing through a Python3 script. I've checked the ref manual and found these sort of command work can be solved using subprocess module.
Then I write the script below:
import subprocess
subprocess.call(["alias", "c=\'uname\'"])
But note that this operation will not take effect to the shell you are currently using, instead, it will use a subshell and then leave. So what this script has done is totally in vain.
So my problem is: how to create an alias in the currently using shell by executing a python script?
In general, you can't
All alias you set in only works in current shell and new aliaes can be added only by shell it self rather than sub-shell or sub-process.
In hack way, you can use gdb to attach you parent shell and change its alias table. But in modern Unix, child process is not allowed to attach parent process. You need to low down the system security level

TO initiate Python shell

You can use subprocess.call("/usr/bin/python") to open Python shell within a piece of Python code. Now my question is is it possible to predefine some variables/functions before initialization of this shell? In other words, inside Python code, I can define a bunch of useful variables and functions and I want them to be available in the Python shell opened later by subprocess call. It is useful in the sense that sometimes you want a customized Python shell to test your environment.
You can do this using the -i switch. This will run a script, and then drop into the interpreter for interactive use.
python -i scriptname.py
Not directly, but I wouldn't do it this way anyways; I'd use code.
Yes, that's something that it's possible and it's useful. In fact, that's something that django provides with the python manage.py shell command.
Looking at the source code for this command should be helpful not only as an example to open a shell with some default configuration, but also to use any shell you like (ipython, bpython or the default one).

Categories