Python 3.8: How does one pass a variable to a Windows CMD subprocess? - python-3.x

Up front confession... I'm a python neophyte. Please forgive any ignorance on my part.
As just a way to learn more, I'm trying to write a script that will take my latest Quicken backup and with 7-Zip, create a compressed and encrypted file with a timestamp in the name. I then want to copy it two two locations.
I have succeeded up the the name part. I've created a variable for the time the script starts and I want to append this to a base file name, but I don't seem to be able to do it. When I've tried, the script runs, but nothing is ever created, no compressed file that is. If I remove what I have with regard to the variable for the filename, I do get a compressed and encrypted file as expected.
Here is what I have so far. The print commands are just there for me making sure I've done the 'today' and 'newfile' variables correctly. Also, I'm doing the testing with just an empty .docx file so that it processes quicker.
Thanks in advance for any/all help or suggestions. I really appreciate it.
from datetime import datetime
from pathlib import Path
today = datetime.now()
print(today.strftime('%Y-%m-%d %H:%M:%S'))
newfile = 'Q2020_' + (today.strftime('%m-%d-%Y_%H%M%S'))
print(newfile)
os.chdir('D:/Quicken Backups')
print(os.getcwd())
import subprocess
cmd= ['C:\\Program Files\\7-Zip\\7z.exe', 'a', '-t7z', '-mx9', '"D:\\Quicken Backups\\Quicken2020\\" + newfile ".7z"', '-ppassword', '-mhe', 'D:\\Quicken Backups\\test.docx']
subprocess.Popen(cmd, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)

Have you thought about using a python package made for zipping, like zipfile?
This way you dont need to deal with opening a subprocess
import zipfile
dest_zip_folder = '2020_backup.zip' # new file name
file_to_zip = 'D:\\Quicken Backups\\test.docx'
zipfile.ZipFile(dest_zip_folder, mode='w').write(file_to_zip)
If you dont want to use that way, I see an error in your code.
You are missing a + after newfile
cmd = [ ...., .... + newfile + '.7zip', ... ]
Also give subprocess.call() a try
import subproccess
cmd = [. . . . . .]
subprocess.call(cmd)

It took a LOT of mucking around with Windows variables syntax and running the subprocess a little differently, but I finally got the thing working, outputting an encrypted file with a date/time stamp in the file name.
For troubleshooting I added the /K to the cmd command so that the window would not close upon completion. This was a HUGE help in trouble shooting this.
Thanks to everyone who even looked at my posted. I hope someday this thread will help someone else!
import os
from pathlib import Path
os.chdir('D:/Quicken Backups')
print(os.getcwd())
import subprocess
cmd = subprocess.Popen('cmd.exe /K ""C:\\Program Files\\7-Zip\\7z.exe" a -t7z -mx9 "D:\\Quicken Backups\\Quicken2020\\Q2020_%DATE:~4,2%-%DATE:~7,2%-%DATE:~-4%_%TIME:~0,2%%TIME:~3,2%%TIME:~8%.7z" -ppassword -mhe "D:\\Quicken Backups\\test.docx"')

Related

Facing a strange "phantom filesystem" issue in Python

I first noticed this problem a bit ago when I posted this thread. Essentially, I'm getting a very strange issue where Python "sees" files that don't actually exist in my file browser when working with files.
As in, if I open a file with an absolute path, modify and print the contents of it through Python, it will print exactly what it's supposed to. But when I try to open the same file through the same absolute path on my Windows file browser, the file is not updated with my modifications.
I experienced a similar issue recently as well - renaming files. Here's a simple script I wrote to replace all spaces in filenames with underscores.
rename.py:
import os
i = 0
path = "E:/sample_path/"
for filename in os.listdir(path):
src = path + filename
dst = path + filename.replace(" ", "_")
os.rename(src, dst)
i += 1
print(str(i) + " files processed.")
Upon doing some prints in Python, I can see that all the files in the directory are being renamed correctly but it just wasn't correctly updating when I actually viewed the directory. Both in the file browser and in using the dir command. Same with creating new files in Python, they exist in the eyes of Python, but they are nowhere to be found in Windows, even with hidden files being visible and all.
Now for the interesting part: This script works if I open the python editor in cmd and import it. So I know it's all correct, no syntax errors or anything - it's just a strange error occurring with Python.
For example, if I go into command prompt and type python rename.py it won't return any errors and will even output the correct results - x files processed. but it will not actually modify any "real" files.
But if I go into command prompt and type python to bring up the cmd editor, then type import rename it gives the correct output and updates all the files correctly. So for the time being this workaround helps, but it's a very strange issue and I have yet to see anyone else encounter it. It's almost like Python creates a temporary duplicate of the filesystem and is not completing it's sync back to Windows.
I've tried reinstalling Python several times, both x64 and x86 verisons and nothing has fixed it so far.
EDIT: Here's a simplified example illustrating my issue.
write.py:
f = open("newfile.txt", "w+")
f.write("hello new file")
f.close()
read.py:
f = open("newfile.txt", "r")
for l in f.readlines():
print(l)
If I run write.py, no errors are returned. But also no file named newfile.txt is visible in my current working directory. However, if I run read.py it prints hello new file. So clearly both of these are accessing the same invisible file somewhere.

python - automatically launch a text file created in the program

I did the search but i couldn't find any help, apologies if i my question is duplicate.
i am writing the code with python 3.6 and in windows environment.in my code, i opened a text file, write the data and close the file.
self.fileName = 'file path'
self.log_file = open(self.fileName, 'w')
self.log_file.write('Write results')
self.lof_file.close()
Instead of the user goes to file path and click to open it, i want to launch the file automatically after python save it.
how do i do that? please help
EDIT:
os.startfile(filepath=self.fileName)
command is working fine, but its opening with default program which is Notepad, how to open the file with specific program, for example, Notepad++
If you know the command line way of doing it, you can use the os module as follows:
import os
self.file = 'file path'
self.log_file = open(self.fileName, 'w')
self.log_file.write('Write results')
self.lof_file.close()
os.system('gedit <file_path>') # for ubuntu, gedit is generally present
For Windows, you can use:
import os
os.startfile('C:\\Users\\RandomUser\\Documents\\test.txt')
Check this answer for more details: https://stackoverflow.com/a/15055133/9332801

Running a cmd command in Python

I am having a problem that I have been spending quite a lot of time on. I have a few lines of code that I run through a bat file, that I would like to run from a Python script instead. This is so that I can feed in variables and create the cmd string throug Python code.
The code is used to run Tableau bridge client to sync a data extract. This is the code and it works when I run it from a BAT file:
#echo off
cd C:\Program Files\Tableau\Tableau 10.3\bin
tableau refreshextract --server https://dub01.online.tableau.com --username "username" --password "password" --site "sitename" --project "project name" --datasource "datasource name" --source-username sql_backend_username --source-password sql_backend_password
I understand that the first line sets the working directory to the folder where Tableau is installed. And the second line does the refreshing.
I have been trying to make this work in Python by just doing something like this:
import os
os.chdir("C:\\Program Files\\Tableau\\Tableau 10.3\\bin")
os.system("tableau -cmd_string_from_above
but all that this does is run the Tableau client, and not the process running the extract. I have been looking at some examples using popen but all of that code is so complex that I dont understand how it actually works.
Hope someone can help me out.
If it works as a bat file, try running that from python.
os.system("start mybatch.bat")
I would recommend you look at the module subprocess
as and example:
subprocess.call(["C:\\Program Files\\Tableau\\Tableau 10.3\\bintableau", "refreshextract", "etc. etc."])
a simpler example:
from subprocess import call
call(["ping", "localhost"])
Ok so building on the code/methods other sugested here I did manage to get it working. It might be kind if a "hacky" solution, but it looks like it is working ok. Here is the example
import json
import os
import subprocess
def refresh_extract(project_name, datasource_name):
#Json file containing most of the variables used
params = json.load(open('all_paths.json'))
server = params['tableau']['server']
username = params['tableau']['username']
password = params['tableau']['password']
site = params['tableau']['site']
source_username = params['tableau']['source-username']
source_password = params['tableau']['source-password']
filepath = "Path to bat file that is called"
executable = os.path.join(filepath, 'tableau_refresh.bat')
#Set the working dir to dir where tableau files used for the call is stored, this is the "hacky" part, needed for the bat to find tableau
os.chdir("C:\\Program Files\\Tableau\\Tableau 10.3\\bin")
p = subprocess.Popen([executable, '%s' %server, '%s' %username, '%s' %password, '%s' %site, '%s' %project_name, '%s' %datasource_name, '%s' %source_username, '%s' %source_password])
return 0
if __name__ == "__main__":
project_name = "project_name"
datasource_name = "data_source_name"
run = refresh_extract(project_name, datasource_name)
Thanks a lot to everyone that helped me figure it out!
This is the code for the bat file just in case it could help someone else
#echo off
#this seems not to be working, therefore I set the working did using
#os.chdir
cd C:\Program Files\Tableau\Tableau 10.3\bin
tableau refreshextract --server %1 --username %2 --password %3 --site %4 --
project %5 --datasource %6 --source-username %7 --source-password %8
PAUSE

How to convert Balsamiq mockups to text strings txt with Python34 script on Windows XP

I've been trying to run these scripts https://github.com/balsamiq/mockups-strings-extractor within XP. I'm getting errors per this screenshot https://www.dropbox.com/s/rlbqp1iytkwvq3m/Screenshot%202014-05-30%2011.57.48.png
Also I tried CD into my test directory and although a text output file is generated it is empty and I still get these errors https://www.dropbox.com/s/odjfbr97e5i4gnn/Screenshot%202014-05-30%2012.09.31.png
Is anybody running Balsamiq on windows able to make this work ?
1) From the looks of the first error pic you included, you were trying to execute a Windows Shell command inside of a Python Interpreter. If you've still got the window open, type quit() before attempting your command again.
2) Your script was written for Python 2.x. If you're using Python 3.x, you'll need to add parentheses to the print lines in the script file and change urllib to urllib.parse. I made the changes below:
import os
import glob
import re
import urllib.parse
for infile in glob.glob( os.path.join(".", '*.bmml') ):
print("STRINGS FOUND IN " + infile)
print("===========================================================")
f = open (infile,"r")
data = f.read()
p = re.compile("<text>(.*?)</text>")
textStrings = p.findall(data)
print(urllib.parse.unquote('\n'.join(textStrings))+"\n")
f.close()
Hope this helps.

Testing python programs without using python shell

I would like to easily test my python programs without constantly using the python shell since each time the program is modified you have to quit, re-enter the python shell and import the program again. I am using a 2012 Macbook pro with OSX. I have the following code:
import sys
def read_strings(filename):
with open(filename) as file:
return file.read().split('>')[1:0]
file1 = sys.argv[1]
filename = read_strings(file1)
Essentially I would like to read into and split a txt file containing:
id1>id2>id3>id4
I am entering this into my command line:
pal-nat184-102-127:python_stuff ceb$ python3 program.py string.txt
However when I try the sys.argv approach on the command line my program returns nothing. Is this a good approach to testing code, could anyone point me in the correct direction?
This is what I would like to happen:
pal-nat184-102-127:python_stuff ceb$ python3 program.py string.txt
['id1', 'id2', 'id3', 'id4']
Let's take this a piece at a time:
However when I try the sys.argv approach on the command line my
program returns nothing
The final result of your program is that it writes a string into the variable filename. It's a little strange to have a program "return" a value. Generally, you want a program to print it's something out or save something to a file. I'm guessing it would ease your debugging if you modified your program by adding,
print (filename)
at the end: you'd be able to see the result of your program.
could anyone point me in the correct direction?
One other debugging note: It can be useful to write your .py files so that they can be run both independently at the command line or in a python shell. How you've currently structured your code, this will work semi-poorly. (Starting a shell and then importing your file will cause an error because sys.argv[1] isn't defined.)
A solution to this is to change your the bottom section of your code as follows:
if __name__ == '__main__':
file1 = sys.argv[1]
filename = read_strings(file1)
The if guard at the top says, "If running as a standalone script, then run what's below me. If you imported me from some place else, then do not execute what's below me."
Feel free to follow up below if I misinterpreted your question.
You never do anything with the result of read_strings. Try:
print(read_strings(file1))

Resources