I have a main project in C:/myproject/harry.py
harry.py is launching threads.
harry.py is saving and loading text documents every few seconds using an already established path self.relativePath = os.path.dirname(sys.argv[0])
Inside each thread, a subprocess is being called to activate a command line .exe file found in C:/myproject/betty/here.exe
I have tried all sorts of things to achieve this such as:
my_env = os.environ
my_env["PATH"] = "/usr/sbin:/sbin:" + my_env["PATH"]
doit = subprocess.Popen('cd betty/', 'here.exe -command', env=my_env)
doit.wait()
or
my_env = os.environ
my_env["PATH"] = "/usr/sbin:/sbin:" + my_env["PATH"]
doit = subprocess.Popen('here.exe -command', cwd='C:/myproject/betty/')
doit.wait()
Response:
FileNotFoundError: [WinError 2] The system cannot find the file specified
Is it possible to run the subprocess inside the subfolder with the custom path ... that will not interfere with the already established path self.relativePath
Thanks,
You were fairly close:
> doit = subprocess.Popen('here.exe -command', cwd='C:/myproject/betty/')
This would actually work if your command were called here.exe -command but of course, no such file exists. You want ['here.exe', '-command'] (or somewhat more unsafely and less efficiently add shell=True; but really, don't).
It seems you forgot to pass in env=my_env in this attempt, too; though does here.exe really require you to modify the PATH? And if it does, repeatedly creating a new copy for each new subprocess seems slightly wasteful.
You'll also want to switch to subprocess.run() or one of the legacy wrappers; you should really only use the low-level Popen() function directly from library functions.
On the other hand, does here.exe really need to run in a particular directory, and does that directory exist on your PATH? Windows is slightly weird and Windows programmers are often unaware of basic command-line usability design principles; but if here.exe is at all correctly written, perhaps you are actually looking for
s = subprocess.run(['c:/myproject/betty/here.exe', '-command'], env=my_env)
I have discovered the answer with some help from various stackoverflow posts on the topic as well as stumbling through possible solutions. It was not easy!
self.relativePath = os.path.dirname(sys.argv[0])
self.relativePath1 = self.relativePath + '\\your_subdirectoryHERE\\'
Be sure to include double slashes, to match os.path.dirname(sys.argv[0])
self.process = subprocess.Popen(self.relativePath1 + 'flare.exe -command', cwd=self.relativePath1)
I need to be able to open a document using its default application in Windows and Mac OS. Basically, I want to do the same thing that happens when you double-click on the document icon in Explorer or Finder. What is the best way to do this in Python?
Use the subprocess module available on Python 2.4+, not os.system(), so you don't have to deal with shell escaping.
import subprocess, os, platform
if platform.system() == 'Darwin': # macOS
subprocess.call(('open', filepath))
elif platform.system() == 'Windows': # Windows
os.startfile(filepath)
else: # linux variants
subprocess.call(('xdg-open', filepath))
The double parentheses are because subprocess.call() wants a sequence as its first argument, so we're using a tuple here. On Linux systems with Gnome there is also a gnome-open command that does the same thing, but xdg-open is the Free Desktop Foundation standard and works across Linux desktop environments.
open and start are command-interpreter things for Mac OS/X and Windows respectively, to do this.
To call them from Python, you can either use subprocess module or os.system().
Here are considerations on which package to use:
You can call them via os.system, which works, but...
Escaping: os.system only works with filenames that don't have any spaces or other shell metacharacters in the pathname (e.g. A:\abc\def\a.txt), or else these need to be escaped. There is shlex.quote for Unix-like systems, but nothing really standard for Windows. Maybe see also python, windows : parsing command lines with shlex
MacOS/X: os.system("open " + shlex.quote(filename))
Windows: os.system("start " + filename) where properly speaking filename should be escaped, too.
You can also call them via subprocess module, but...
For Python 2.7 and newer, simply use
subprocess.check_call(['open', filename])
In Python 3.5+ you can equivalently use the slightly more complex but also somewhat more versatile
subprocess.run(['open', filename], check=True)
If you need to be compatible all the way back to Python 2.4, you can use subprocess.call() and implement your own error checking:
try:
retcode = subprocess.call("open " + filename, shell=True)
if retcode < 0:
print >>sys.stderr, "Child was terminated by signal", -retcode
else:
print >>sys.stderr, "Child returned", retcode
except OSError, e:
print >>sys.stderr, "Execution failed:", e
Now, what are the advantages of using subprocess?
Security: In theory, this is more secure, but in fact we're needing to execute a command line one way or the other; in either environment, we need the environment and services to interpret, get paths, and so forth. In neither case are we executing arbitrary text, so it doesn't have an inherent "but you can type 'filename ; rm -rf /'" problem, and if the file name can be corrupted, using subprocess.call gives us little additional protection.
Error handling: It doesn't actually give us any more error detection, we're still depending on the retcode in either case; but the behavior to explicitly raise an exception in the case of an error will certainly help you notice if there is a failure (though in some scenarios, a traceback might not at all be more helpful than simply ignoring the error).
Spawns a (non-blocking) subprocess: We don't need to wait for the child process, since we're by problem statement starting a separate process.
To the objection "But subprocess is preferred." However, os.system() is not deprecated, and it's in some sense the simplest tool for this particular job. Conclusion: using os.system() is therefore also a correct answer.
A marked disadvantage is that the Windows start command requires you to pass in shell=True which negates most of the benefits of using subprocess.
I prefer:
os.startfile(path, 'open')
Note that this module supports filenames that have spaces in their folders and files e.g.
A:\abc\folder with spaces\file with-spaces.txt
(python docs) 'open' does not have to be added (it is the default). The docs specifically mention that this is like double-clicking on a file's icon in Windows Explorer.
This solution is windows only.
Just for completeness (it wasn't in the question), xdg-open will do the same on Linux.
import os
import subprocess
def click_on_file(filename):
'''Open document with default application in Python.'''
try:
os.startfile(filename)
except AttributeError:
subprocess.call(['open', filename])
If you have to use an heuristic method, you may consider webbrowser.
It's standard library and despite of its name it would also try to open files:
Note that on some platforms, trying to open a filename using this
function, may work and start the operating system’s associated
program. However, this is neither supported nor portable.
(Reference)
I tried this code and it worked fine in Windows 7 and Ubuntu Natty:
import webbrowser
webbrowser.open("path_to_file")
This code also works fine in Windows XP Professional, using Internet Explorer 8.
If you want to go the subprocess.call() way, it should look like this on Windows:
import subprocess
subprocess.call(('cmd', '/C', 'start', '', FILE_NAME))
You can't just use:
subprocess.call(('start', FILE_NAME))
because start is not an executable but a command of the cmd.exe program. This works:
subprocess.call(('cmd', '/C', 'start', FILE_NAME))
but only if there are no spaces in the FILE_NAME.
While subprocess.call method enquotes the parameters properly, the start command has a rather strange syntax, where:
start notes.txt
does something else than:
start "notes.txt"
The first quoted string should set the title of the window. To make it work with spaces, we have to do:
start "" "my notes.txt"
which is what the code on top does.
Start does not support long path names and white spaces. You have to convert it to 8.3 compatible paths.
import subprocess
import win32api
filename = "C:\\Documents and Settings\\user\\Desktop\file.avi"
filename_short = win32api.GetShortPathName(filename)
subprocess.Popen('start ' + filename_short, shell=True )
The file has to exist in order to work with the API call.
os.startfile(path, 'open') under Windows is good because when spaces exist in the directory, os.system('start', path_name) can't open the app correctly and when the i18n exist in the directory, os.system needs to change the unicode to the codec of the console in Windows.
I am pretty late to the lot, but here is a solution using the windows api. This always opens the associated application.
import ctypes
shell32 = ctypes.windll.shell32
file = 'somedocument.doc'
shell32.ShellExecuteA(0,"open",file,0,0,5)
A lot of magic constants. The first zero is the hwnd of the current program. Can be zero. The other two zeros are optional parameters (parameters and directory). 5 == SW_SHOW, it specifies how to execute the app.
Read the
ShellExecute API docs for more info.
Here is the answer from Nick, adjusted slightly for WSL:
import os
import sys
import logging
import subprocess
def get_platform():
if sys.platform == 'linux':
try:
proc_version = open('/proc/version').read()
if 'Microsoft' in proc_version:
return 'wsl'
except:
pass
return sys.platform
def open_with_default_app(filename):
platform = get_platform()
if platform == 'darwin':
subprocess.call(('open', filename))
elif platform in ['win64', 'win32']:
os.startfile(filename.replace('/','\\'))
elif platform == 'wsl':
subprocess.call('cmd.exe /C start'.split() + [filename])
else: # linux variants
subprocess.call(('xdg-open', filename))
If you want to specify the app to open the file with on Mac OS X, use this:
os.system("open -a [app name] [file name]")
On windows 8.1, below have worked while other given ways with subprocess.call fails with path has spaces in it.
subprocess.call('cmd /c start "" "any file path with spaces"')
By utilizing this and other's answers before, here's an inline code which works on multiple platforms.
import sys, os, subprocess
subprocess.call(('cmd /c start "" "'+ filepath +'"') if os.name is 'nt' else ('open' if sys.platform.startswith('darwin') else 'xdg-open', filepath))
On mac os you can call open:
import os
os.open("open myfile.txt")
This would open the file with TextEdit, or whatever app is set as default for this filetype.
I think you might want to open file in editor.
For Windows
subprocess.Popen(["notepad", filename])
For Linux
subprocess.Popen(["text-editor", filename])
I built a small library combining the best answers here for cross-platform support:
$ pip install universal-startfile
then launch a file or URL:
from startfile import startfile
startfile("~/Downloads/example.png")
startfile("http://example.com")
I was getting an error when calling my open file() function. I was following along with a guide but the guide was written in windows while I'm on Linux. So the os.statrfile method wasn't working for me. I was able to alleviate this problem by doing the following:
Import libraries
import sys, os, subprocess
import tkinter
import tkinter.filedioalog as fd
import tkinter.messagebox as mb
After the lib imports I then called the subprocess method for opening a file in unix based OS which is "xdg-open" and the file that will be opened.
def open_file():
file = fd.askopenfilename(title='Choose a file of any type', filetypes=[('All files', "*.*")])
subprocess.call(['xdg-open', file])
I am writing a method to open a path in the explorer window in Mac. So, I am using getstatusoutput method of commands module in python. I have the following piece of code :
Path = "file:///" + USERHOME
filePath = os.path.join(Path, filePath)
ret, out = commands.getstatusoutput('open "%s"' % filePath)
This method is working for most of the files/folders except one named as "old,;'{}&". In this case, it is working if I don't put "file:///" before the actual Path as mentioned above. I did not understand why this is happening. Can anyone point out what am I missing here ?
If you are on version 2.7+ don't use the commands module. It's deprecated and replaced by the subprocess module.
Secondly don't use the file:/// prefix. Use the -R flag to tell open to reveal it in Finder. From the open man-page:
-R Reveals the file(s) in the Finder instead of opening them.
Example:
import subprocess
subprocess.Popen(["open", "-R", "/path/to/myfile/old,;'{}&"])
I'm attempting to read and write files from a User Directory, (C:\Users\USERNAME\Test Source) But I've been unsuccessful in finding any resources on how I can auto detect the name of the user, USERNAME in the above example, or anyway that I can have it read and write to the directory without knowledge off what a users name is.
Could anyone point me towards the right direction or methods for this, if it's even a logical request? I'm not sure how much difference, if any, it makes but this program is being written in Python 2.7.
The simplest way is this:
import os
print os.path.expanduser('~')
Append your folder to the path like so:
userdir = os.path.expanduser('~')
print os.path.join(userdir, 'Test Source')
Besides requiring the least lines of code, this method has the advantage of working under every OS (Linux, Windows XP / 7 / 8 / etc).
You can use in windows command line
echo %username%
or
whoami
for getting the username of the user who is currently logged in .
Store it in a variable and then append it to the path name.
You can also use
‘C:\users\%username%\file‘
directly .To check through whoami do
l=`whoami`
echo $l
Use the %userprofile% variable in your path if you're on Windows:
%userprofile%\Test Source\file.txt
Try:
>>> import getpass
>>> import os.path
>>> usename = getpass.getuser()
>>> mypath = os.path.join("C:\Users", username, "Test Source")
I am trying to use paramiko to download a file via SFTP. I create the SFTP object like this:
transport = paramiko.Transport((sftp_server, sftp_port))
transport.connect(username = sftp_login, password = sftp_password)
sftp = paramiko.SFTPClient.from_transport(transport)
sftp.get("file_name", '.', None)
and, I get the exception:
Exception python : Folder not found: \\$IP_ADDRESS\folder_1/folder_2\file_name.
I'm running paramiko to connect to a client chrooted SFTP. The file, 'file_name', is located at the root of my client's chroot.
I don't get why I have this error showing apparently the full path (outside the chroot) of my client's server.
I don't know why my dummy file is not going to be downloaded :O
I will provide any necessary information.
The following code worked for me in Ubuntu 11.10:
sftp.get("file_name", "file_name")
I just made a couple of changes that shouldn't affect to your problem:
localpath: Used full path to the local file name instead of just '.' (directories aren't allowed)
callback: Removed it since None is already the default value and that's not really needed
Since I'm not getting the same error you're getting regarding the remotepath parameter, I guess you might be using a different sftp server that has a different behaviour.
My advice would be to:
Verify with another client, for example the sftp command, that the file you're looking for is really where you are trying to get it.
Use sftp.chdir just to make sure that the default directory being used is the one you expect.
I hope this helps.