I am trying to run a simple command in python:
from subprocess import *
check_output("ls")
When I run this it raises
Error:
WindowsError: [Error 2] The system cannot find the file specified
ls doesn’t exist on Windows; dir does. Furthermore, you may need to pass shell=True, since it’s built in to cmd.exe.
If it’s not a test and you just want to get the contents of a directory, use os.listdir instead.
Related
The goal is to open a particular excel file using a python shell subprocess. The code cannot be more simple yet I cannot figure out what is wrong:
import subprocess
arg1 = "C:\\Program Files (x86)\\Microsoft Office\\root\\Office16\\EXCEL.EXE"
arg2 = "C:\\Users\\user\\Documents\\test.xlsm"
p = subprocess.Popen(["start", arg1, arg2], shell=False)
The command works perfectly directly on the shell but when done through subprocess throws the following error:
FileNotFoundError: [WinError 2] The system cannot find the file specified
I have also tried the below which works equally fine directly on the shell but the behavior is different:
p = subprocess.Popen([arg1, arg2], shell=False)
The following failed assertion pops up from Excel:
snapshopt error
My next try was:
import os
os.system("C:\\Users\\user\\Documents\\test.xlsm")
Which replicates the same assertion error as above plus returns a code 3 which based on
System Error Codes (0-499)
is a path not found.
Again same path works on shell, at this stage I run out of ideas, any help?
os.startfile is actually a better way to do it. As specified in the documentation -
os.startfile(path[, operation])
Start a file with its associated application.
When operation is not specified or 'open', this acts like
double-clicking the file in Windows Explorer, or giving the file name
as an argument to the start command from the interactive command
shell: the file is opened with whatever application (if any) its
extension is associated.
When another operation is given, it must be a “command verb” that
specifies what should be done with the file. Common verbs documented
by Microsoft are 'print' and 'edit' (to be used on files) as well as
'explore' and 'find' (to be used on directories)
You can just do the following -
import os
os.startfile("C:\\Users\\user\\Documents\\test.xlsm")
I'm trying to run code from this repo: https://github.com/tylin/coco-caption, specifically from https://github.com/tylin/coco-caption/blob/master/pycocoevalcap/tokenizer/ptbtokenizer.py, line 51-52:
p_tokenizer = subprocess.Popen(cmd, cwd=path_to_jar_dirname, \
stdout=subprocess.PIPE)
The error I get running this is
OSError: [Errno 2] No such file or directory
I can't figure out why the file can't be found.
The jar I'm trying to run is:
stanford-corenlp-3.4.1.jar
You can see the structure of directory by going to https://github.com/tylin/coco-caption/tree/master/pycocoevalcap/tokenizer. For more specificity into what my actual arguments are when I run the line of code:
cmd= ['java', '-cp', 'stanford-corenlp-3.4.1.jar', 'edu.stanford.nlp.process.PTBTokenizer', '-preserveLines', '-lowerCase', 'tmpWS5p0Z'],
and
path_to_dirname =abs_path_to_folder/tokenizer
I can see the jar that needs to be run, and it looks to be in the right place, so why can't python find it. (Note: I'm using python2.7.) And the temporary File 'tmpWS5p0Z' is where it should be.
Edit: I'm using Ubuntu
try an absolute path ( meaning the path beginning from root / )
https://en.wikipedia.org/wiki/Path_(computing)#Absolute_and_relative_paths
for relative paths in python see i.e. Relative paths in Python , How to refer to relative paths of resources when working with a code repository in Python
UPDATE:
As a test try subprocess.Popen() with the shell=True option and give an absolute path for any involved file, including tmpWS5p0Z
in this subprocess.Popen() call are involved two paths :
1) the python path, python has to find the java executable and the stanford-corenlp-3.4.1.jar which is essentially a java program with its own path
2) the java path of stanford-corenlp-3.4.1.jar
as this is all too complicated try
p_tokenizer = subprocess.Popen(['/absolute_path_to/java -cp /absolute_path_to/stanford-corenlp-3.4.1.jar /absolute_path_to/edu.stanford.nlp.process.PTBTokenizer -preserveLines -lowerCase /absolute_path_to/tmpWS5p0Z' ], shell=True)
Python specify popen working directory via argument
Python subprocess.Popen() error (No such file or directory)
Just in case it might help someone:
I was struggling with the same problem (same https://github.com/tylin/coco-caption code). Might be relevant to say that I was running the code with python 3.7 on CentOS using qsub. So I changed
cmd = ['java', '-cp', 'stanford-corenlp-3.4.1.jar', 'edu.stanford.nlp.process.PTBTokenizer', '-preserveLines', '-lowerCase', 'tmpWS5p0Z']
to
cmd = ['/abs/path/to/java -cp /abs/path/to/stanford-corenlp-3.4.1.jar edu.stanford.nlp.process.PTBTokenizer -preserveLines -lowerCase ', ' /abs/path/to/temporary_file']
Using absolute paths fixed the OSError: [Errno 2] No such file or directory. Notice that I still put '/abs/path/to/temporary_file' as second element in the cmd list, because it got added later on. But then something went wrong in the tokenizer java subprocess, I don't know why or what, just observing because:
p_tokenizer = subprocess.Popen(cmd, cwd=path_to_jar_dirname, stdout=subprocess.PIPE, shell=True)
token_lines = p_tokenizer.communicate(input=sentences.rstrip())[0]
Here token_lines was an empty list (which is not the wanted behavior). Executing this in IPython resulted in the following (just the subprocess.Popen(..., not the communicate).
Exception in thread "main" edu.stanford.nlp.io.RuntimeIOException: java.io.IOException: Input/output error
at edu.stanford.nlp.process.PTBTokenizer.getNext(PTBTokenizer.java:278)
at edu.stanford.nlp.process.PTBTokenizer.getNext(PTBTokenizer.java:163)
at edu.stanford.nlp.process.AbstractTokenizer.hasNext(AbstractTokenizer.java:55)
at edu.stanford.nlp.process.PTBTokenizer.tokReader(PTBTokenizer.java:444)
at edu.stanford.nlp.process.PTBTokenizer.tok(PTBTokenizer.java:416)
at edu.stanford.nlp.process.PTBTokenizer.main(PTBTokenizer.java:760)
Caused by: java.io.IOException: Input/output error
at java.base/java.io.FileInputStream.readBytes(Native Method)
at java.base/java.io.FileInputStream.read(FileInputStream.java:279)
at java.base/java.io.BufferedInputStream.read1(BufferedInputStream.java:290)
at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:351)
at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.base/java.io.InputStreamReader.read(InputStreamReader.java:185)
at java.base/java.io.BufferedReader.read1(BufferedReader.java:210)
at java.base/java.io.BufferedReader.read(BufferedReader.java:287)
at edu.stanford.nlp.process.PTBLexer.zzRefill(PTBLexer.java:24511)
at edu.stanford.nlp.process.PTBLexer.next(PTBLexer.java:24718)
at edu.stanford.nlp.process.PTBTokenizer.getNext(PTBTokenizer.java:276)
... 5 more
Again, I don't know why or what, but I just wanted to share that doing this fixed it:
cmd = ['/abs/path/to/java -cp /abs/path/to/stanford-corenlp-3.4.1.jar edu.stanford.nlp.process.PTBTokenizer -preserveLines -lowerCase /abs/path/to/temporary_file']
And changing cmd.append(os.path.join(path_to_jar_dirname, os.path.basename(tmp_file.name))) into cmd[0] += os.path.join(path_to_jar_dirname, os.path.basename(tmp_file.name)).
So making cmd into a list with only 1 element, containing the entire command with absolute paths at once. Thanks for your help!
As #Lars mentioned above the issue I had was that I Java wasn't installed. Solved it with:
sudo apt update
sudo apt install default-jdk
sudo apt install default-jre
Making this post since I had this issue twice (due to reinstallation problems) and forgot about it.
I have a python script that reads and writes to files that are located relative to it, in directories above and beside it. When I run my script via Cygwin using
python script.py
The program works perfectly. However, when I run it by navigating through the windows GUI to my file and double clicking, I get a blank cmd prompt and then my program runs fine until I reach the point where I need to access the other files, at which point it fails and gives me this message in the cmd prompt that opens itself:
../FFPRM.TXT
../2025510296/FFPRM_000.TXT
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\rbanks\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1549, in __call__
return self.func(*args)
File "C:\Users\rbanks\Desktop\TSAC\EXECUTABLE\T-SAC_GUI.py", line 705, in run_exe
invalid_entry, output_text = self.apply()
File "C:\Users\rbanks\Desktop\TSAC\EXECUTABLE\T-SAC_GUI.py", line 694, in apply
p = subprocess.Popen(['cp', output_file_path, output_file_path_id])
File "C:\Users\rbanks\AppData\Local\Programs\Python\Python35-32\lib\subprocess.py", line 950, in __init__
restore_signals, start_new_session)
File "C:\Users\rbanks\AppData\Local\Programs\Python\Python35-32\lib\subprocess.py", line 1220, in _execute_child startupinfo)
FileNotFoundError: [WinError 2] The system cannot find the file specified
I am deploying this script as well as the directory structure as a zip for users to be able to unzip and use anywhere on their PC, so it is important for me to be able to run it with a simple double click and my relative file paths.
My first thought was the cmd prompt that was opening and executing my script was in a different environment, but when I run:
cd
pause
in a .cmd script, I get:
C:\Users\rbanks\Desktop\TSAC\EXECUTABLE>pause
Which is the correct location.
I am not having any luck with Google, I assume because I can't seem to construct a sufficient search query. Could someone point me in the right direction please?
[edit] the other answer is correct(at least i suspect) but i will leave this here in the hopes that it helps the op in the future with path problems ... and doing something like this is just generally good practice
use
BASEPATH = os.path.abspath(os.path.dirname(__file__))
at the top of your script
the later
txt_file = os.path.join(BASEPATH,"my_file.txt")
or even
txt_file = os.path.join(BASEPATH,"..","my_file.txt")
this gives you the benefit of being able to do things like
if not os.path.exists(txt_file):
print "Cannot find file: %r"%txt_file
which will likely give you a better idea about what your problem might actually be (if its simply path related at least)
The problem is not the current directory. It is correct when double clicking on the icon
The problem is: Cygwin commands are not in the windows path
You are using python, so don't run simple copy commands like this, which make your script non-portable and subject to variations, requiring installation of cygwin, etc...
p = subprocess.Popen(['cp', output_file_path, output_file_path_id])
can be replaced by
import shutil
shutil.copyfile(output_file_path, output_file_path_id)
shutil module complements os module for file manipulation functions that aren't native in the operating system.
now you have a 100% pythonic solution, native, which will throw exceptions if cannot read/write files, so fully integrated in the rest of your program.
Before running an external command from Python make sure that no python way exists. There are so many useful modules out there.
Other examples of how to avoid running basic commands from python (of course if you need to run a C compilation it's different!):
zipfile package: much better than running zip.exe
gzip package: can open gzipped files natively from python
os.listdir() instead of parsing the output of cmd /c dir /B
os.remove() instead of calling rm or del
etc... python rules!
I want get into virtual environment in python files.But it raise no such files.
import subprocess
subprocess.Popen(['source', '/Users/XX/Desktop/mio/worker/venv/bin/activate'])
Traceback (most recent call last):
File "/Users/Ru/Desktop/mio/worker/run.py", line 3, in
subprocess.Popen(['source', '/Users/Ru/Desktop/mio/worker/venv/bin/activate'])
File"/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 710, in init
errread, errwrite)
File"/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 1335, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
I think your code doesn't work because you are separating the 'source' command from the virtualenv path argument, from the documentation:
"Note in particular that options (such as -input) and arguments (such
as eggs.txt) that are separated by whitespace in the shell go in
separate list elements, while arguments that need quoting or
backslash escaping when used in the shell (such as filenames
containing spaces or the echo command shown above) are single list
elements."
You should try one of two things:
First, write the source and the virtualenv file path as a single string argument:
import subprocess
subprocess.Popen(['source '/Users/XX/Desktop/mio/worker/venv/bin/activate'])
I'm working on OSX and that doesn't seem to work, but it might be due to the shell you are using. To ensure this will work, you can use the shell=True flag:
import subprocess
subprocess.Popen(['source '/Users/XX/Desktop/mio/worker/venv/bin/activate'],shell=True)
This will use /bin/sh shell by default. Again, you can read more in the documentation.
Tom.
There is another simpler way to do what you want.
If you want a python script to use a virtualenv you can always use the python interpreter from the virualenv itself.
/Users/Ru/Desktop/mio/worker/venv/bin/python my_python_file.py
This will run the my_python_file.py with the properties/libraries of the virtualenv.
If you want to run that file inside a subprocess you can do something similar to the method I described above:
import subprocess
subprocess.Popen(['/Users/Ru/Desktop/mio/worker/venv/bin/python my_python_file.py])
and have my_python_file.py import pika and do other actions you wish to do.
Tom.
With Python 3.4.2 on Windows I want to open the explorer with the folder of the currently running script like this:
import os, subprocess
subprocess.check_call(['explorer', os.path.dirname(__file__)])
Instead I see that the explorer is opened by with a default folder
"C:\Users\XX\Documents" and an error is thrown:
Traceback (most recent call last):
File "C:/XXX/YYY.py", line 9, in <module>
subprocess.check_call(['explorer', os.path.dirname(__file__)])
File "C:\Python34\lib\subprocess.py", line 561, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['explorer', 'C:/XXX']' returned non-zero exit status 1
and although os.path.dirname returns paths with slashes on Windows (backslashes are path seperators) you can copy and paste it into the explorer and it will open the location just fine. (XXX is the path part, YYY the file name part)
Furthermore, if you manually write the path as it is in the explorer (with backslashes), even then the command fails.
subprocess.check_call(['explorer', r'C:\Users'])
But at least the explorer will open the right directory despite of throwing the same error (so maybe using call instead of check_call).
What's going on here? How can I show the folder of the running Python script file in the explorer?
You need to send the absolute path to the directory by calling os.path.abspath, and switch check_call with call (as you suspected).
import os
import subprocess
dirname = (os.path.dirname(os.path.abspath(__file__)))
subprocess.call(['explorer', dirname])
subprocess.check_call raises an exception if the return code of the process is nonzero. Even when explorer doesn't actually have an error, it has a non-zero return status, so you get an exception.
That's actually unrelated to the problem, though. The problem is that you were passing a string with forward slashes to explorer. This would have happened if you called your script like python path/to/script.py instead of python path\to\script.py. If you pass the absolute path to subprocess.call, explorer will open in the right directory. You would get the same error if you passed an empty string as the second arg to subprocess.call.
You need to use backslashes in your paths for windows explorer to undestand them. Testing from the command line, this works:
> explorer C:\Users
But this doesn't
> explorer C:/Users
Use os.path.normpath to convert the forward slashes into back slashes
Note that abspath, according to the docs, is implemented as normpath(join(os.getcwd(), path)), so the other solution also addresses this issue.