I have a shell script from which I am creating some logfile in a directory. And this shell script I am executing in python as below.
cmd = "sh xyz.sh"
try:
subprocess.call(cmd,shell=True)
except OSError:
print "Failed to run the script.:
I want to attach the timestamp on those created logfile which is getting created by xyz.sh script. For this I want to use below python code.
b=time.strftime("%x")
c=time.strftime("%X")
ts=b+"_"+c
I want to attach the result of 'ts' variable on created log file. For example : if logfile is name as abc.log and output of ts is : 6/19/2016_10:20:16 then my logfile should renamed as 6/19/2016_10:20:16_abc.log
Please help me to achieve this.
If you already know the name of the generated logfile, you can use os.rename to rename it. Something along the lines of :
import time, os
b = time.strftime("%x")
c = time.strftime("%X")
ts = b + "_" + c
os.rename("abc.log", ts + "_abc.log")
If you don't know the name of the logfile, you can find it using os.listdir(os.getcwd()), which will give you a list with all the files of the current directory (i.e. the one from where you are running your script).
Related
I'm trying to create a python script to convert into exe which just deletes itself. When I run it as .py file it works. The code is this:
import os
os.remove(os.getcwd + "\\test.py")
I'm working in Windows that's why I'm using \\ and the file is obviously named test.py. But when I convert it into an exe file (I've tried both with py2exe and pyinstaller) it gives me access denied error. Does anyone know how to fix this?
PS: Yes, I've changed the name to test.exe if you're asking.
It won't be this simple.
1) When you are running the script actually it is the python.exe executing the statements and the script file (test.py) is free. In this way python.exe can delete the script.
2) When you convert convert your script to exe, it is the exe file itself executing, which means the file is 'busy', or said in other words - used by the process, and it cannot be deleted.
Find a way to start another process, which would delete the file after you exit the current process.
Edit(sample code):
import sys
import ctypes
import platform
import subprocess
def execute(command, async=False):
"""
if async=False Executes a shell command and waits until termination and
returns process exit code
if async=True Executes a shell command without waiting for its
termination and returns subprocess.Popen object
On Windows, does not create a console window.
"""
if async:
call = subprocess.Popen
else:
call = subprocess.call
if platform.system() == 'Windows':
# the following CREATE_NO_WINDOW flag runs the process without
# a console window
# it is ignored if the application is not a console application
return call(command, creationflags=0x08000000)
else:
return call(command)
def main():
ctypes.windll.user32.MessageBoxA(0, __file__, 'Show path', 0)
ctypes.windll.user32.MessageBoxA(0, sys.executable, 'sys.executable', 0)
with open(r'D:\delete_me.py', 'w') as f:
f.write('import os\n')
f.write('import time\n')
f.write('time.sleep(2)\n')
f.write('os.remove(r"{}")'.format(sys.executable))
execute(r'C:\Python27\python.exe D:\delete_me.py', async=True)
if __name__ == '__main__':
main()
And this was compiled with `pyinstaller.exe --onefile --windowed D:\self_delete.py
execute function is something we use to execute calls on both Linux and Windows and I just copied it. This is why the platform check is there.
You can use some .bat file with timeout instead of sleep or whatever else you want if you can't execute delete_me.py
What you can do is to use a VBScript to do this. What I have done is made this:
deleteFile is the location of the exe you want to delete. It doesnt matter if its running or not, If its running then it will first be terminated forcefully then deleted, then the VBScript will delete itself too. All this will happen without the console window opening to make it more convenient for the end user. The Python Code is listed below this code
deleteFile ="Install.exe"
Dim oShell : Set oShell = CreateObject("WScript.Shell")
oShell.Run "taskkill /f /im install.exe", 0, True
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(deleteFile) Then
Set fs = CreateObject("Scripting.Filesystemobject")
fs.DeleteFile(deleteFile)
Else
End If
Set oFso = CreateObject("Scripting.FileSystemObject") : oFso.DeleteFile Wscript.ScriptFullName, True
The Python Code:
Here you will have to change \Filename.extention to \Yourfilename.yourfilextension for ex. \example.exe
import os
fname = "Filename.extention"
path = os.getcwd() + "\\" + fname
delcode = f'''deleteFile ="{path}"
Dim oShell : Set oShell = CreateObject("WScript.Shell")
oShell.Run "taskkill /f /im install.exe", 0, True
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(deleteFile) Then
Set fs = CreateObject("Scripting.Filesystemobject")
fs.DeleteFile(deleteFile)
Else
End If
Set oFso = CreateObject("Scripting.FileSystemObject") : oFso.DeleteFile Wscript.ScriptFullName, True'''
f = open("C:\Windows\Temp\delete.vbs", "w")
f.write(delcode)
os.startfile("C:\Windows\Temp\delete.vbs")
The only think you need to do is to add the python code to a function, then change what I said above and just run the function. I have tested it myself and it worked perfectly so there should be no errors in the code
Edit: I know its very old thread but I just wanted to put my answer too since I felt it was easier than others + I was also finding an answer myself to this question so why not to help others too incase someone comes across the same question!
I've been trying to run a Java program and capture it's STDOUT output to a file from the Python script. The idea is to run test files through my program and check if it matches the answers.
Per this and this SO questions, using subprocess.call is the way to go. In the code below, I am doing subprocess.call(command, stdout=f) where f is the file I opened.
The resulted file is empty and I can't quite understand why.
import glob
test_path = '/path/to/my/testfiles/'
class_path = '/path/to/classfiles/'
jar_path = '/path/to/external_jar/'
test_pattern = 'test_case*'
temp_file = 'res'
tests = glob.glob(test_path + test_pattern) # find all test files
for i, tc in enumerate(tests):
with open(test_path+temp_file, 'w') as f:
# cd into directory where the class files are and run the program
command = 'cd {p} ; java -cp {cp} package.MyProgram {tc_p}'
.format(p=class_path,
cp=jar_path,
tc_p=test_path + tc)
# execute the command and direct all STDOUT to file
subprocess.call(command.split(), stdout=f, stderr=subprocess.STDOUT)
# diff is just a lambda func that uses os.system('diff')
exec_code = diff(answers[i], test_path + temp_file)
if exec_code == BAD:
scream(':(')
I checked the docs for subprocess and they recommended using subprocess.run (added in Python 3.5). The run method returns the instance of CompletedProcess, which has a stdout field. I inspected it and the stdout was an empty string. This explained why the file f I tried to create was empty.
Even though the exit code was 0 (success) from the subprocess.call, it didn't mean that my Java program actually got executed. I ended up fixing this bug by breaking down command into two parts.
If you notice, I initially tried to cd into correct directory and then execute the Java file -- all in one command. I ended up removing cd from command and did the os.chdir(class_path) instead. The command now contained only the string to run the Java program. This did the trick.
So, the code looked like this:
good_code = 0
# Assume the same variables defined as in the original question
os.chdir(class_path) # get into the class files directory first
for i, tc in enumerate(tests):
with open(test_path+temp_file, 'w') as f:
# run the program
command = 'java -cp {cp} package.MyProgram {tc_p}'
.format(cp=jar_path,
tc_p=test_path + tc)
# runs the command and redirects it into the file f
# stores the instance of CompletedProcess
out = subprocess.run(command.split(), stdout=f)
# you can access useful info now
assert out.returncode == good_code
I asked already and few people gave good advises but there were to many unknowns for me as I am beginner. Therefore I decided to ask for help again without giving bad code.
I need a script which will execute copy files to directory while the other is still running.
Basically I run first command, it generates files (until user press enter) and then those files are gone (automatically removed).
What I would like to have is to copying those files (without have to press "Enter" as well).
I made in bash however I would like to achieve this on python. Please see below:
while kill -0 $! 2>/dev/null;do
cp -v /tmp/directory/* /tmp/
done
If first script is purely command line : it should be fully manageable with a python script.
General architecture :
python scripts starts first one with subprocess module
reads output from first script until it gets the message asking for pressing enter
copies all files from source directory to destination directory
sends \r into first script input
waits first script terminates
exits
General requirements :
first script must be purely CLI one
first script must write to standart output/error and read from standard input - if it reads/writes to physical terminal (/dev/tty on Unix/Linux or con: on Dos/Windows), it won't work
the end of processing must be identifiable in standard output/error
if the two above requirement were no met, the only way would be to wait a define amount of time
Optional operation :
if there are other interactions in first script (read and/or write), it will be necessary to add the redirections in the script, it is certainly feasible, but will be a little harder
Configuration :
the command to be run
the string (from command output) that indicates first program has finished processing
the source directory
the destination directory
a pattern for file name to be copied
if time defined and no identifiable string in output : the delay to wait before copying
A script like that should be simple to write and test and able to manage the first script as you want.
Edit : here is an example of such a script, still without timeout management.
import subprocess
import os
import shutil
import re
# default values for command execution - to be configured at installation
defCommand = "test.bat"
defEnd = "Appuyez"
defSource = "."
defDest = ".."
# BEWARE : pattern is in regex format !
defPattern="x.*\.txt"
class Launcher(object):
'''
Helper to launch a command, wait for a defined string from stderr or stdout
of the command, copy files from a source folder to a destination folder,
and write a newline to the stdin of the command.
Limits : use blocking IO without timeout'''
def __init__(self, command=defCommand, end=defEnd, source=defSource,
dest=defDest, pattern = defPattern):
self.command = command
self.end = end
self.source = source
self.dest = dest
self.pattern = pattern
def start(self):
'Actualy starts the command and copies the files'
found = False
pipes = os.pipe() # use explicit pipes to mix stdout and stderr
rx = re.compile(self.pattern)
cmd = subprocess.Popen(self.command, shell=True, stdin=subprocess.PIPE,
stdout=pipes[1], stderr=pipes[1])
os.close(pipes[1])
while True:
txt = os.read(pipes[0], 1024)
#print(txt) # for debug
if str(txt).find(self.end) != -1:
found = True
break
# only try to copy files if end string found
if found:
for file in os.listdir(self.source):
if rx.match(file):
shutil.copy(os.path.join(self.source, file), self.dest)
print("Copied : %s" % (file,))
# copy done : write the newline to command input
cmd.stdin.write(b"\n")
cmd.stdin.close()
try:
cmd.wait()
print("Command terminated with %d status" % (cmd.returncode,))
except:
print("Calling terminate ...")
cmd.terminate()
os.close(pipes[0])
# allows to use the file either as an imported module or directly as a script
if __name__ == '__main__':
# parse optional parameters
import argparse
parser = argparse.ArgumentParser(description='Launch a command and copy files')
parser.add_argument('--command', '-c', nargs = 1, default = defCommand,
help="full text of the command to launch")
parser.add_argument('--endString', '-e', nargs = 1, default = defEnd,
dest="end",
help="string that denotes that command has finished processing")
parser.add_argument('--source', '-s', nargs = 1, default = defSource,
help="source folder")
parser.add_argument('--dest', '-d', nargs = 1, default = defDest,
help = "destination folder")
parser.add_argument('--pattern', '-p', nargs = 1, default = defPattern,
help = "pattern (regex format) for files to be copied")
args = parser.parse_args()
# create and start a Launcher ...
launcher = Launcher(args.command, args.end, args.source, args.dest,
args.pattern)
launcher.start()
I've been trying to trouble this for days now, and would appreciate some help --
Basically, I wrote the following Python script
import os, sys
# =__=__=__=__=__=__=__ START MAIN =__=__=__=__=__=__=__
if __name__ == '__main__':
# initialize variables
all_files = []
# directory to download data siphon files to
dDir = '/path/to/download/directory/'
# my S3 bucket
s3bucket = "com.mybucket/"
foldername = "test"
# get a list of available feeds
feeds = <huge JSON object with URLs to feeds>
for item in range(feeds['count']):
# ...check if the directory exists, and if not, create the directory...
if not os.path.exists(folderName):
os.makedirs(folderName)
... ... ...
# Loop through all the splits
for s in dsSplits:
... ... ...
location = requestFeedLocation(name, timestamp)
... ... ...
downloadFeed(location[0], folderName, nameNotGZ)
# THIS IS WHERE I AM HAVING PROBLEMS!!!!!!!!!!!
cmd = 's3cmd sync 'dDir+folderName+'/ s3://'+s3bucket+'/'
os.system(cmd)
Everything in my code works...when I run this straight from the command line, everything runs as expected...however, when I have it executed via cron -- the following DOES NOT execute (everything else does)
# THIS IS WHERE I AM HAVING PROBLEMS!!!!!!!!!!!
cmd = 's3cmd sync 'dDir+folderName+'/ s3://'+s3bucket+'/'
os.system(cmd)
To answer a few questions, I am running the cron as root, s3cmd is configured for the root user, OS is Ubuntu 12.04, python version is 2.7, all of the necessary directories have Read / Write permissions...
What am I missing?
First check variable 'foldername' in command you have used N in variable.
In command syntax you need to add plus (+) sign in prefix like +dDir+folderName+
So I hope command would be like below..
cmd = 's3cmd sync '+dDir+foldername+'/ s3://'+s3bucket+'/'
os.system(cmd)
Here I found some more s3cmd sync help: http://tecadmin.net/s3cmd-file-sync-with-s3bucket/
OpenShift has these default dir's:
# $_ENV['OPENSHIFT_INTERNAL_IP'] - IP Address assigned to the application
# $_ENV['OPENSHIFT_GEAR_NAME'] - Application name
# $_ENV['OPENSHIFT_GEAR_DIR'] - Application dir
# $_ENV['OPENSHIFT_DATA_DIR'] - For persistent storage (between pushes)
# $_ENV['OPENSHIFT_TMP_DIR'] - Temp storage (unmodified files deleted after 10 days)
How do reference them in a python script?
Example script "created a log file in log directory and log in data directory?
from time import strftime
now= strftime("%Y-%m-%d %H:%M:%S")
fn = "${OPENSHIFT_LOG_DIR}/test.log"
fn2 = "${OPENSHIFT_DATA_DIR}/test.log"
#fn = "test.txt"
input = "appended text " + now + " \n"
with open(fn, "ab") as f:
f.write(input)
with open(fn2, "ab") as f:
f.write(input)
Can these script be used with cron?
EDIT the BASH File:
#! /bin/bash
#date >> ${OPENSHIFT_LOG_DIR}/new.log
source $OPENSHIFT_HOMEDIR/python-2.6/virtenv/bin/activate
python file.py
date >> ${OPENSHIFT_DATA_DIR}/new2data.log
import os
os.getenv("OPENSHIFT_INTERNAL_IP")
should work.
So with your example, modify to:-
import os
OPENSHIFT_LOG_DIR = os.getenv("OPENSHIFT_LOG_DIR")
fn = os.path.join(OPENSHIFT_LOG_DIR, "test.log")
And, yes, you can call this python script with a cron by referencing your bash script if you want... Like this for example:-
#!/bin/bash
date >> ${OPENSHIFT_LOG_DIR}/status.log
chmod +x status
cd ${OPENSHIFT_REPO_DIR}/wsgi/crawler
nohup python file.py 2>&1 &
Those variables OPENSHIFT_* are provided as environment variables on OpenShift -- so the $_ENV["OPENSHIFT_LOG_DIR"] is an example to get the value inside a php script.
In python, the equivalent would just be os.getenv("OPENSHIFT_LOG_DIR").
Made edits to Calvin's post above and submitted 'em.
Re: the question of where file.py exists -- use os.getenv("OPENSHIFT_REPO_DIR") as the base directory where all your code would be located on the gear where you app is running.
So if your file is located in .openshift/misc/file.py -- then just use:
os.path.join(os.getenv("OPENSHIFT_REPO_DIR"), ".openshift", "misc", "file.py")
to get the full path.
Or in bash, the equivalent would be:
$OPENSHIFT_REPO_DIR/.openshift/misc/file.py
HTH