Problems running batch files with Python - python

I am rather new to Python and have been trying to run a .cmd file with it, but it won't run it from the correct location. My file Run_setup.cmd, is setting up another a different software with a bunch of related files and so I have sequestered them to their own folder for my sanity.
Currently I can get the .cmd file to run from the same location as my source code. I know I am messing up the file path for it with cwd=r'%s' based on what the documentation says, but I don't get how.
If cwd is not None, the function changes the working directory to cwd before executing the child. cwd can be a str and path-like object. In particular, the function looks for executable (or for the first item in args) relative to cwd if the executable path is a relative path.
I currently have it using cwd=r' C:\LargeFolder\Files\CorrectFolder' based off this post, and it seems that it works for any file path, but I can't seem to get it to work for me.
from subprocess import Popen
def runCmdfile():
# File Path to source code: 'C:\LargeFolder\Files'
myDir = os.getcwd()
# File Path to .cmd file: 'C:\LargeFolder\Files\CorrectFolder'
myDir = myDir + '\CorrectFolder'
runThis = Popen('Run_setup.cmd', cwd=r'%s' % myDir)
stdout, stderr = runThis.communicate()
What am I missing here, and furthermore what is the purpose of using cwd=r' ' ?

this one works for me:
def runCmdfile():
# File Path to source code: 'C:\LargeFolder\Files'
myDir = os.getcwd()
# File Path to .cmd file: 'C:\LargeFolder\Files\CorrectFolder'
myDir = os.path.join(myDir, 'CorrectFolder')
# Popen does not take cwd into account for the file to execute
# so we build the FULL PATH on our own
runThis = Popen(os.path.join(myDir, 'Run_setup.cmd'), cwd=myDir)
stdout, stderr = runThis.communicate()

the parameter is cwd=. The r"" part only needs to exist in the definition of your string, to have a raw string and make python ignore special sequences using backslashes.
Since your string comes from os.getcwd, you don't need it.
def runCmdfile():
# File Path to source code: 'C:\LargeFolder\Files'
myDir = os.getcwd()
# File Path to .cmd file: 'C:\LargeFolder\Files\CorrectFolder'
myDir = os.path.join(myDir, 'CorrectFolder')
runThis = Popen('Run_setup.cmd', cwd=myDir)
stdout, stderr = runThis.communicate()

Your error is due to not escaping your \.
You need to escape your "\" where you're adding in your subfolder and then you should be good to go.
myDir = myDir + '\CorrectFolder'
should be
myDir = myDir + '\\CorrectFolder'

Related

Python split and subsequent join on os.sep does not yield properly joint string

python 3.8 on Windows 10
I'm trying to create a script to automatically create a .bat file to activate the correct environment or the current script. For this I need to do some path manipulation, which includes in essence the following code:
import os
cwd = os.getcwd()
s = cwd.split(os.sep)
n = os.path.join(*s,'test.bat')
print(n)
Expected outcome:
C:\\Data\\test.bat
Actual outcome:
C:Data\\test.bat
This is missing the \ separator after the drive.
Also with deeper folder structures, this goes wrong only in joining the drive. What is going wrong here?
Full code:
import os
python_file = 'python_file_name.py' # file to run
program_name = 'Start Python Program' # Name of the resulting BAT file
cwd = os.getcwd() # directory in which the Python file lives
env = os.environ['CONDA_PREFIX'] # environment name in Conda
act = os.environ['CONDA_EXE'].split(os.sep)[:-1] # activate.bat lives in the same directory as conda.exe
act = os.path.join(*act,'activate.bat')
# Construct the commands
text = f'''ECHO ON
CD {cwd}
CALL {act} {env}
CALL {python_file}
'''
with open(f'{program_name}.bat', 'w') as f:
f.write(text)
Strangely enough this seems to be a feature, not a bug...
https://docs.python.org/3/library/os.path.html

Python os.chdir() not working with path with spaces and special characters

I'm trying to run some files sequentially (scrape.py, tag.py, save.py and select.py) that are located in a folder named 'cargen'. However, when I try to make os.chdir(path) to access this 'cargen' folder, I'm getting an Exception message because in the path to 'cargen' folder there's a directory with spaces and special characters on it.
The code to run the files sequentially looks like the following:
import os
path = "C:/Users/Desktop/repl/Special Cháracters/cargen/"
os.chdir(path)
directory = 'C:/Users/Desktop/scrap/'
files = ['scrape', 'tag', 'save', 'select']
if __name__ == '__main__':
if not os.path.isdir(directory):
os.mkdir(directory)
[os.system('python ' + path + f'{file}.py ' + directory) for file in files]
The message that I'm getting looks like this:
python: can't open file 'C:/Users/Desktop/repl/\Special': [Errno 2] No such file or directory
I've tried to move to files to a path where there aren't any special characters or spaces in the path and the code works perfectly. Could anybody please help me with this? How should I define the path to 'cargen' to be able to access these files?
NOTE: I'm using Windows 10 with Anaconda
When windows reads comands it uses spaces as separators. e.g.:
my folder -> command1: my, command2: folder
But you can join them adding quotation marks you can join the separated commands in one.
"my folder" -> command1: my folder
I think something similiar is appening to you, try to declare your path like that:
'"your path"'
Finally, the problem wasn't the os.chdir(). The problem was related to os.system() function as #user2357112 mentioned.
The os.system() command was giving me problems due to the spaces in the path. Thus, as the files are all located in the same folder, I have just eliminated that reference to path, resulting in something like:
import os
path = os.getcwd()
os.chdir(path)
directory = 'C:/Users/Desktop/scrap/'
files = ['scrape', 'tag', 'save', 'select']
if __name__ == '__main__':
if not os.path.isdir(directory):
os.mkdir(directory)
[os.system('python ' + f'{file}.py ' + directory) for file in files]

How to use the current folder the program is in?

When I open a file, I have to specify the directory that it is in. Is there a way to specify using the current directory instead of writing out the path name? I'm using:
source = os.listdir("../mydirectory")
But the program will only work if it is placed in a directory called "mydirectory". I want the program to work in the directory it is in, no matter what the name is.
def copyfiles(servername):
source = os.listdir("../mydirectory") # directory where original configs are located
destination = '//' + servername + r'/c$/remotedir/' # destination server directory
for files in source:
if files.endswith("myfile.config"):
try:
os.makedirs(destination, exist_ok=True)
shutil.copy(files,destination)
except:
this is a pathlib version:
from pathlib import Path
HERE = Path(__file__).parent
source = list((HERE / "../mydirectory").iterdir())
if you prefer os.path:
import os.path
HERE = os.path.dirname(__file__)
source = os.listdir(os.path.join(HERE, "../mydirectory"))
note: this will often be different from the current working directory
os.getcwd() # or '.'
__file__ is the filename of your current python file. HERE is now the path of the directory where your python file lives.
'.' stands for the current directory.
try:
os.listdir('./')
or:
os.listdir(os.getcwd())

DJANGO 1.9 | views.py | execute *.bat file | location for save file

I have 2 questions(I could not find answer on stackoverflow):
First question:
I added run_command.bat file to:
DjangoProj/
---DjangoApp/
------views.py
------run_command.bat
In method save_logs in DjangoProj/DjangoApp/views.py I tried:
def save_logs(request):
choosenMachines = request.GET.getlist('mvsMachine')
(data,errors) = subprocess.Popen(r'run_command.bat' + str(choosenMachines), shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE).communicate()
But I got this error:
the run_command.bat is not recognize as external or internal command,
exec file or batch file
I suppose that Django is currently in another path(the question is which)
And second question:
Where is saved txt file created by method from DjangoProj/DjangoApp/views.py
def set_parameters_on_ftp(request):
with open('start_task.txt', 'w') as f:
for command in commands:
f.write(command+'\n')
return
It suppose it should be in: DjangoProj/DjangoApp/*
For the first question:
import os
#Set myPath variable to the path of the file being executed
myPath = os.path.dirname(os.path.abspath(__file__))
#Change current working directory to myPath
os.chdir(myPath)
#Or change current working directory to a subdirectory of myPath
os.chdir(os.path.join(myPath, 'subFolder'))
For the second question:
import os
#Check the current working directory. The txt file is getting saved here.
os.getcwd()
#This can be changed by changing the working directory as described in the answer to the first question.
EDIT: Changed the os.chdir() syntax error in the first part.
Your guess was true.
Django current running path is not in your project folder.
In my testing it was in C:\Python27
you must give exact path or use PROJECT_ROOT variable in settings file.
Have fun

Python: Check if data file exists relative to source code file

I have a small text (XML) file that I want a Python function to load. The location of the text file is always in a fixed relative position to the Python function code.
For example, on my local computer, the files text.xml and mycode.py could reside in:
/a/b/text.xml
/a/c/mycode.py
Later at run time, the files could reside in:
/mnt/x/b/text.xml
/mnt/x/c/mycode.py
How do I ensure I can load in the file? Do I need the absolute path? I see that I can use os.path.isfile, but that presumes I have a path.
you can do a call as follows:
import os
BASE_DIR = os.path.dirname(os.path.realpath(__file__))
This will get you the directory of the python file you're calling from mycode.py
then accessing the xml files is as simple as:
xml_file = "{}/../text.xml".format(BASE_DIR)
fin = open(xml_file, 'r+')
If the parent directory of the two directories are always the same this should work:
import os
path_to_script = os.path.realpath(__file__)
parent_directory = os.path.dirname(path_to_script)
for root, dirs, files in os.walk(parent_directory):
for file in files:
if file == 'text.xml':
path_to_xml = os.path.join(root, file)
You can use the special variable __file__ which gives you the current file name (see http://docs.python.org/2/reference/datamodel.html).
So in your first example, you can reference text.xml this way in mycode.py:
xml_path = os.path.join(__file__, '..', '..', 'text.xml')

Categories

Resources