I'm setting a bash variable in the main shell by reading the content of a file with
srclang="$(cat ${langdir}/srclang.log)
The value is "en-GB" and it prints just fine.
I then call a function that, in turn, calls a python script, but when I try to access this variable with
os.environ["srclang"]
From the python script, I get the following error
File "/usr/lib/python3.6/os.py", line 669, in __getitem__
raise KeyError(key) from None
KeyError: 'srclang'
How can I pass this variable from the function to the python script?
EDIT:
After reading a little more on it, it seems like I have to export it, but exporting is also giving me an error:
export: `en-GB': not a valid identifier
Related
I'm using check_output to do all my SSH and GitHub setup, and I'm attempting to execute eval $(ssh-agent), both to start the agent and to parse the output if I need the process id.
from subprocess import check_output
out = check_output(["eval", "$(ssh-agent)"])
print(out)
But regardless of how I escape things, I get the same error.
Traceback (most recent call last):
File "gitSetup.py", line 3, in <module>
out = check_output(["eval", "$(ssh-agent)"])
File "/usr/lib/python2.7/subprocess.py", line 216, in check_output
process = Popen(stdout=PIPE, *popenargs, **kwargs)
File "/usr/lib/python2.7/subprocess.py", line 394, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1047, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
I'm wondering if I'm not escaping or trimming my arguments properly; if anyone sees my error, I'd appreciate some insight!
Even if you managed to fix the superficial syntax problems, a subprocess which runs successfully simply then terminates without a trace; it doesn't attempt to (and couldn't, even if it wanted to) modify the environment of the parent Python process. This is a common FAQ.
You could run the eval in the parent process which starts your Python script, or perhaps figure out how to communicate with ssh-agent directly from Python. Its output is usually a simple sequence of variable assignments, which you can parse yourself.
from subprocess import check_output
from os import environ
eval_string = check_output(['ssh-agent'])
for line in eval_string.rstrip('\n').split('\n'):
for expr in line.rstrip(';').split(';'):
if expr.startswith((' export ', 'echo ')):
continue
var, value = expr.strip().split('=', 1)
environ[var] = value
If the output from ssh-agent contains shell quoting, you will need to perform additional parsing on it (basically, trim the quotes around the value string). But this is already rather clunky and brittle, so perhaps revert to setting up the environment before launching Python instead of trying to splash some sophistication onto this kludge.
In more detail, ssh-agent and a precious few other shell utilities have a very specific design in order for them to be able to communicate with their parent process. Precisely because a subprocess cannot make any changes in the environment of its parent process, it instead prints a piece of code for its parent process to execute. By default, it prints sh code like this:
SSH_AUTH_SOCK=/tmp/ssh-MUyniqn10506/agent.10506; export SSH_AUTH_SOCK;
SSH_AGENT_PID=10507; export SSH_AGENT_PID;
echo Agent pid 10507;
There is also an option for it to print similar code in csh syntax (this is a historical shell which thankfully isn't used much any longer) but, alas, no option for producing Python code. (It would not be hard to make ssh-agent do that, per se.)
(The above output sample copy/pasted from http://blog.joncairns.com/2013/12/understanding-ssh-agent-and-ssh-add/ which contains a fuller explanation.)
This question already has answers here:
python subprocess.call() "no such file or directory"
(2 answers)
Closed 4 years ago.
I'm attempting to run an old script which takes an .mdb file and converts it into a MySQL database. However, I'm running into an issue where I receive the following error.
File "/usr/lib64/python2.7/subprocess.py", line 568, in check_output
process = Popen(stdout=PIPE, *popenargs, **kwargs)
File "/usr/lib64/python2.7/subprocess.py", line 711, in __init__
errread, errwrite)
File "/usr/lib64/python2.7/subprocess.py", line 1327, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
I have attempted to research this error, but all I found was fixes where the item was not correctly formatted as a list. So, I've modified the affected code where subprocess.py is called, and changed it to the following:
def get_external_command_output(command):
args = shlex.split(command)
print "################"
print type(args), args
ret = subprocess.check_output(args) # this needs Python 2.7 or higher
return ret
Which in turn returns the same error, but also the below message is printed:
<type 'list'> ['mdb-tables', '-1', '/mnt/data/General/Genit/WIP/IL_Orders.mdb']
So I can safely say that the arguments are correctly formatted as a list. I'm really unsure how else to tackle this issue, because all the help forums I've found suggest the same issue. The argument isn't a list. However, I can see that mine is.
Could anybody provide some guidance here?
Many thanks.
There can be number of reasons for this. The error comes from your underlying OS (ENOENT).
The easiest to would be to try running the same thing:
mdb-tables -1 /mnt/data/General/Genit/WIP/IL_Orders.mdb
(or just mdb-tables really) and see what happens, what complain you get from your shell.
Among possible reasons would be:
As mentioned by Peter Wood in the comments. If you just pass an executable name to run, it must be located in one of the directories listed in your PATH environmental variable. Or, you have to use either path to the executable which is either absolute or relative to current working directory (based on where you ran the parent from or cwd argument passed to subprocess.check_output call). E.g. ./mdb-tables if in the same directory where you were when you ran the parent script or to which cwd was set.
It is also possible. Esp. if it's an older script. That you have specified an interpreter that no longer exists on your host. In that case the same error (ENOENT) would be raised. You might see a slightly different error message (hinting at bad interpreter) if executed directly from shell, but it would look identical when called as subprocess from python.
You've hinted mdb-tables is also a script. But otherwise previous paragraph would also hold true for dynamically linked ELF binaries. If they were built with and expected a version (path) of dynamic linker (their interpreter) no longer available on the system. You can print path of the expected dynamic linker binary for instance by running objdump -sj .interp BINARY_IN_QUESTION.
I have a python script that I want to automate so I created a simple bash script (called mybash.sh).
#!/bin/sh
vars="C:\Users\Jane\Desktop\Work\variables.csv"
while IFS="," read gname gid
do
echo "Gene Name: $gname"
echo "Gene ID: $gid"
python alignment.py work_file $gid > C:\\Users\\Jane\\Desktop\\Work_Done\\$gname.fa
done < "$vars"
read -rn1
It is a huge script but I always get an error saying that the last line of my alignment.py script has a NameError, so after running my bash script from windows cmd prompt as >mybash.sh I get this:
Gene Name: cytb
Gene ID: ENSB0010011
Traceback (most recent call last):
File "alignment.py", line 99, in <module>
for species in geneDict:
NameError: name 'geneDict' is not defined
The geneDict is the very last part of the python script which simply creates a fasta alignment file for a gene for all species in separate folder.
When I execute the python script normally in cmd prompt, it works perfectly fine but instead of extracting the gname (gene name) and gid (gene ID) from a variables file, I was typing it manually. I didn't want to do that for 200 genes. I can't understand why it no longer finishes and says that the geneDict is no longer defined?
Also, I tried making the python script run in a bash script alone as follows:
#!/bin/sh
python alignment.py work_file ENSB0010011 > C:\\Users\\Jane\\Desktop\\Work_Done\\cytb.fa
And this worked fine also, the python script did not stop working all of a sudden and my file came out. How do I make the python script execute without error, while pulling the variables from variables.csv separately so that I don't have to type it in manually?
The last bit of the python script is as follows:
for species in geneDict: # this is where it says geneDict is not defined
print '>' + species
print geneDict[species]
NameError exception is raised because global variable "geneDict" is not defined in python script. See https://docs.python.org/2/library/exceptions.html#exceptions.NameError
I am trying to write a python script where in the argument that is passed to this script, needs to be used as an argument to a command that will be executed in this script.
Executing this script on cygwin
eg:-
x.py file1
inside x.py script:
file = sys.argv[1]
data = os.popen('ar t file').read()
when this command is executed the value of file is not taken(i.e file1),rather the 'file' variable is being considered as a file, and hence throws an error:filename 'file' cannot be found.Is it possible to pass the value of file as an argument to this command.
Thanks,
Akhilesh
This is nothing to do with command arguments or passing them on, but a basic misunderstanding of strings. You have a hard-coded string containing the word "file", you are not actually passing in the value of the file variable anywhere. You can use string substitution:
data = os.popen('ar t {}'.format(file)).read()
or
data = os.popen('ar t %s' % file).read()
My class assignment is to read a file called key.txt on a server which is in the same directory of a python script it is running on port 2323. The code running in the script is as follows:
while 1: print eval(raw_input("Enter Math:"))
I'm connecting with PuTTY and every time I run any code, the connection instantly drops if the code I pass is invalid. It gives no explanation, but I assume the eval function couldnt parse my code.
Here are some of the things I've tried and their outputs:
Entering open('key.txt', 'r').read() (or any explicit code) killed the connection
Using chr(#) to pass in commands, ex. hello = chr(104)+chr(101)+chr(108)+chr(108)+chr(111). The server just spits back whatever I type
Using compile by entering compile('print "Hello!"', 'buttfile', 'exec'), with the output <code object <module> at 0x7f6270ac0db0, file "buttfile", line 1>
Those are the only two ways I can think of that allows me to pass in code. I wrote a small cpp program to convert whatever I type into the char combinations, as well as including newlines so I can enter multiline code with the chr() method.
So my question is how would I execute code to read a file through python's eval function?
If you are connecting to a linux system you can do it in two commands:
__import__("os").system("locate key.txt")
This assumes that the locate db is up to date.
Then when you know the location just use:
__import__("os").system("cat /location/of/file/key.txt")
Which will output the key to the screen.