Background
I use the command dir/s in batch files all the time. But, I am unable to call this using python. NOTE: I am using Python 2.7.3.
Code
import subprocess
subprocess.call(["dir/s"])
Error Message
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
subprocess.call(["dir/s"])
File "C:\Python27\lib\subprocess.py", line 493, in call
return Popen(*popenargs, **kwargs).wait()
File "C:\Python27\lib\subprocess.py", line 679, in __init__
errread, errwrite)
File "C:\Python27\lib\subprocess.py", line 896, in _execute_child
startupinfo)
WindowsError: [Error 2] The system cannot find the file specified
I have tried changing the quotations but nothing has worked.
How would I call the dir/s module using subprocess?
How about
subprocess.call("dir/s", shell=True)
Not verified.
This is a lot different than what you're asking but it solves the same problem. Additionally, it solves it in a pythonic, multiplatform way:
import fnmatch
import os
def recglob(directory, ext):
l = []
for root, dirnames, filenames in os.walk(directory):
for filename in fnmatch.filter(filenames, ext):
l.append(os.path.join(root, filename))
return l
You need a space between dir and /s. So break it into an array of 2 elements. Also as carlosdoc pointed out, you would need to add shell=True, since the dir command is a shell builtin.
import subprocess
subprocess.call(["dir", "/s"], shell=True)
But if you're trying to get a directory listing, make it OS independent by using the functions available in the os module such as os.listdir(), os.chdir()
I finally found the answer. To list all directories in a directory (e.g. D:\\, C:\\) on needs to first import the os module.
import os
Then, they need to say that they want to list everything. Within that, they need to make sure that the output is printed.
for top, dirs, files in os.walk('D:\\'):
for nm in files:
print os.path.join(top, nm)
That was how I was able to solve it. Thanks to this.
As it's an inbuilt part of the command line you need to run it as:
import subprocess
subprocess.call("cmd /c dir /s")
Related
I am writing something in Python where I want to use predefined texts from files within the package. Somehow I can't manage to get it to work in Eclipse PyDev Console.
This is my path structure. From "story.py" I want to use the content of "starttext".
I tried open() with multiple variations of os.getcwd() and os.path.dirname(sys.argv[0]) which resulted in
FileNotFoundError: [Errno 2] No such file or directory: '..\starttext'
My last attempt was trying something like
import pkg_resources
resource_package = __name__
resource_path = '/'.join(('.', 'starttext'))
template = pkg_resources.resource_stream(resource_package, resource_path)
resulting in:
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "C:\Program Files\Python\Python36-64\lib\site-packages\pkg_resources\__init__.py", line 1232, in resource_stream
self, resource_name
File "C:\Program Files\Python\Python36-64\lib\site-packages\pkg_resources\__init__.py", line 1479, in get_resource_stream
return io.BytesIO(self.get_resource_string(manager, resource_name))
File "C:\Program Files\Python\Python36-64\lib\site-packages\pkg_resources\__init__.py", line 1482, in get_resource_string
return self._get(self._fn(self.module_path, resource_name))
File "C:\Program Files\Python\Python36-64\lib\site-packages\pkg_resources\__init__.py", line 1560, in _get
"Can't perform this operation for loaders without 'get_data()'"
NotImplementedError: Can't perform this operation for loaders without 'get_data()'
which appears to have something to do with python 3.x?
This seems to be such an easy task and I don't understand whats wrong.
Any help is appreciated.
Thank you.
update
Thanks to ShmulikA I changed it to:
from os.path import dirname, join, abspath
filename = join(dirname(abspath(communitybot.anthology.teststory.story.__file__)), 'starttext')
file = open(filename, 'r')
content = file.read()
This works although I think it is a little bit long, but I'm certain I am still doing something wrong there.
seems like you are missing a \ - use os.path.join:
from os.path import dirname, join, abspath
filename = join(dirname(abspath(__file__)), 'starttext')
file = open(filename, 'r')
__file__ - the path to the module's source file (you can also do import requests;requests.__file__)
os.path.abspath - returns the absolute filename (e.g. abspath('..') returns /home)
os.path.dirname - returns the dirname of a file
os.path.join - joins a file parts compatible on both linux and windows
I'm trying to write a script that will automatically extract the files from a rar or zip folder and put them somewhere, so as to make file organization faster. Included are the relevant sections of code:
import shutil
import os
import eyed3
import glob
import zipfile
import rarfile
import unrar
import patoolib
## create zipfile object of the downloaded album and get a tracklist
rarfile.UNRAR_TOOL=r'C:\Users\John\AppData\Local\Programs\Python\Python36-32'
downloads = glob.glob("C:\\Users\\John\\Downloads\\*")
music_zip = max(downloads, key=os.path.getctime)
if os.path.splitext(music_zip)[-1] == '.zip':
music_folder = zipfile.ZipFile(music_zip)
elif os.path.splitext(music_zip)[-1] == '.rar':
music_folder = rarfile.RarFile(music_zip)
print(music_zip)
print(music_folder)
temporary_album_folder = 'C:\\Users\\John\\Downloads\\temporary_album_folder'
if not os.path.exists(temporary_album_folder):
os.makedirs(temporary_album_folder)
# patoolib.extract_archive(music_zip, outdir=temporary_album_folder)
# temp_list = os.listdir(temporary_album_folder)
# tag = eyeD3.load(temp_list[0])
# artist = tag.getArtist()
# album = tag.getAlbum()
# print(os.getcwd())
os.chdir(temporary_album_folder)
music_folder.extractall()
music_folder.close()
print(temporary_album_folder)
When I run this, I expect it to successfully extract the contents of the RAR into a temporary folder in \Downloads. Instead, the error message that I get when I try to run this in the console is:
C:\Users\John\Documents\PythonScripts>music_organizer.py
C:\Users\John\Downloads\d1ctus t3 n3c4r3(5).rar
<rarfile.RarFile object at 0x02C16350>
Traceback (most recent call last):
File "C:\Users\John\Documents\PythonScripts\music_organizer.py", line 40, in <
module>
music_folder.extractall()
File "C:\Users\John\AppData\Local\Programs\Python\Python36-32\lib\site-package
s\rarfile.py", line 820, in extractall
self._extract(fnlist, path, pwd)
File "C:\Users\John\AppData\Local\Programs\Python\Python36-32\lib\site-package
s\rarfile.py", line 885, in _extract
p = custom_popen(cmd)
File "C:\Users\John\AppData\Local\Programs\Python\Python36-32\lib\site-package
s\rarfile.py", line 2813, in custom_popen
creationflags=creationflags)
File "C:\Users\John\AppData\Local\Programs\Python\Python36-32\lib\subprocess.p
y", line 707, in __init__
restore_signals, start_new_session)
File "C:\Users\John\AppData\Local\Programs\Python\Python36-32\lib\subprocess.p
y", line 990, in _execute_child
startupinfo)
PermissionError: [WinError 5] Access is denied
I know a lot of other people have asked similar questions about WinError 5 and Python, so to address possible common suggestions in advance: I am running the terminal in admin mode, have turned off UAC, have unblocked the folder in question, and have opened full permissions to the folder and sub-folders in question. Does anyone know why this is happening and possible get arounds? Any help much appreciated.
Refer to: Eryksun's comment
It's not a security permission issue. UNRAR_TOOL should be the executable name (optionally the full path) of an unrar program. subprocess.Popen is failing because you're trying to execute the "Python36-32" directory. – eryksun yesterday
The Windows API has some rather useless error code mappings. Internally in the NT API the error in this case is STATUS_FILE_IS_A_DIRECTORY (0xC00000BA), which could not be more obvious, but it gets mapped to ERROR_ACCESS_DENIED (0x0005) by Windows, which misleads you into thinking it's a problem with file or object permissions. – eryksun yesterday
I'm trying to make a script that crawls through the Applications directory and open up a given file. So here is my code
import os, subprocess
os.chdir('/Applications')
root = '.'
for path, dirs, files in os.walk(root):
#print path
for f in files:
if f == 'Atom':
subprocess.call([f])
break
So I have three questions.
At first I used Atom as the example to execute the script. It opens up fine, but even after opening the app the loop doesn't break and keeps crawling.
Second, the Atom app doesn't open up as it would normally do. It opens up in the directory of the applications folder, which looks something like this.
While it should merely look like this,
And the very important problem is that it didn't work for any other applications which I couldn't understand. Here is the error output when I tried to open AppStore.
./App Store.app
./App Store.app/Contents
./App Store.app/Contents/_CodeSignature
./App Store.app/Contents/MacOS
Traceback (most recent call last):
File "control_files.py", line 32, in <module>
subprocess.call([f])
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 522, in call
return Popen(*popenargs, **kwargs).wait()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 709, in __init__
errread, errwrite)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 1326, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
What could possibly be the problem?
The previous answers are spot-on about break only exiting the innermost loop.
Another way to escape the loop, and probably neater, would be to hide away this functionality in a function and return from it. Something along the lines of:
def open_program(root, filename):
for path, dirs, files in os.walk(root):
if filename in files:
full_path = os.path.join(path, filename)
subprocess.call([full_path])
return
IMO using filename in files makes the code cleaner, and does pretty much the same work.
I would like to convert dozens of excel sheets to csv files at once. I have a working .vbs file which makes the conversion, and I would like to execute this .vbs file on the different sheets with the help of a python code. I have the following 2 versions of the python code:
Version 1:
import os
import sys
import subprocess
FolderName=sys.argv[1]
FileList=os.listdir(FolderName)
NewList=[]
for i in FileList:
NewItem=i.split('.xls')
NewXls=FolderName+"\\"+NewItem[0]+".xlsx "
NewCsv=FolderName+"\\"+NewItem[0]+".csv"
NewCommand="C:\\Users\\user\\XlsToCsv.vbs "+sys.argv[2]+" "+NewXls+NewCsv
subprocess.call(NewCommand)
Version 2:
import os
import sys
import subprocess
def main(directory,extension,sheet):
for filename in os.listdir(directory):
if filename.endswith(extension):
path = os.path.join(directory, filename)
base = os.path.join(directory, filename[:len(filename)-len(extension)])
print base
new_xls = base + extension
new_csv = base + '.csv'
subprocess.call(['C:\\Users\\user\\XlsToCsv.vbs', sheet, new_xls, new_csv])
main(sys.argv[1],sys.argv[2],sys.argv[3])
It does not matter, which I try, I get the same error message:
Traceback (most recent call last):
File "C:/Users/user/Desktop/Work/XlsDir.py", line 16, in <module>
subprocess.call(NewCommand)
File "C:\Python27\lib\subprocess.py", line 524, in call
return Popen(*popenargs, **kwargs).wait()
File "C:\Python27\lib\subprocess.py", line 711, in __init__
errread, errwrite)
File "C:\Python27\lib\subprocess.py", line 948, in _execute_child
startupinfo)
WindowsError: [Error 193] %1 er ikke et gyldigt Win32-program
The last line of the error message means approximately, that it is not a valid Win32-program.
What I have tried so far:
If I run the .vbs file from command prompt with the right arguments (sheet, name of the .xls file and name of the .csv file) then it works fine.
If I print the commands that python generates and copy them into command prompt, they work fine.
I tried every combinations of '\' and '\' within the different paths, and nothing got any better.
I tried to execute the programs with replacing the sys.argv[i] arguments with specific arguments and then execute the .py file from command prompt. I get the same error message.
I hope some of you can help me. Thanks a lot!
To elaborate on Ansgar's remedy:
Starting a .vbs from the command line 'works', because the shell associates the extension .vbs with an application (e.g. cscript/wscript; see ftype, assoc, cscript //E, cescript //S).
subprocess.call() does not open a shell, so either specify the application (c|wscript.exe) or start the shell yourself:
import subprocess
#subprocess.call("notepad") # works
#subprocess.call("dir") # [Error 2] The system cannot find the file specified
# no shell, no intrinsics
#subprocess.call("19112944.vbs") # [Error 193] %1 is not a valid Win32 application
# no shell, can't associate .vbs with c|wscript.exe
subprocess.call("cscript 19112944.vbs") # works
subprocess.call("cmd /c 19112944.vbs") # works
# have shell, can associate .vbs with c|wscript.exe
Try running the script with cscript.exe:
subprocess.call(['cscript.exe', 'C:\\Users\\user\\XlsToCsv.vbs', sheet, new_xls, new_csv])
I have a function that runs lessc (installed with npm install -g less):
>>> import subprocess
>>> subprocess.Popen(['lessc'])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\subprocess.py", line 679, in __init__
errread, errwrite)
File "C:\Python27\lib\subprocess.py", line 896, in _execute_child
startupinfo)
WindowsError: [Error 2] The system cannot find the file specified
Unfortunately, it doesn't work unless I add shell=True:
>>> subprocess.Popen(['lessc'], shell=True)
<subprocess.Popen object at 0x01F619D0>
What can I do to make lessc run without using shell=True?
From both https://docs.python.org/3/library/subprocess.html#subprocess.Popen and https://docs.python.org/2/library/subprocess.html#subprocess.Popen:
You do not need shell=True to run a batch file or console-based executable.
as already cited by #JBernardo.
So, lets try:
where lessc actually tells
C:\Users\myname\AppData\Roaming\npm\lessc
C:\Users\myname\AppData\Roaming\npm\lessc.cmd
That means, the file to execute is lessc.cmd, not some .bat file. And indeed:
>>> import subprocess
>>> subprocess.Popen([r'C:\Users\myname\AppData\Roaming\npm\lessc.cmd'])
<subprocess.Popen object at 0x035BA070>
>>> lessc: no input files
usage: lessc [option option=parameter ...] <source> [destination]
So, this does work if you specify the full path. I assume there was a typo involved when you had this experience. May be you wrote .bat instead of .cmd?
If you don't want to patch the full path of lessc into your script, you can bake yourself a where:
import plaform
import os
def where(file_name):
# inspired by http://nedbatchelder.com/code/utilities/wh.py
# see also: http://stackoverflow.com/questions/11210104/
path_sep = ":" if platform.system() == "Linux" else ";"
path_ext = [''] if platform.system() == "Linux" or '.' in file_name else os.environ["PATHEXT"].split(path_sep)
for d in os.environ["PATH"].split(path_sep):
for e in path_ext:
file_path = os.path.join(d, file_name + e)
if os.path.exists(file_path):
return file_path
raise Exception(file_name + " not found")
Then you can write:
import subprocess
subprocess.Popen([where('lessc')])
Change the file to lessc.bat, or create .bat file that calls lessc. That way the file will be recognized by Windows as a batch file and will be executed properly.
You may also need to set cwd in addition to this depending on where the .bat file is.