A python script that outputs windows batch file. - python

I am working on a python script that will walk through a large collection of .py files and write out individual .bat files that can be called upon to run these scripts.
I understand typical python output
directory = 'c:/'
OPATH = open(str(directory) + 'output_file.txt', 'w')
However if I try to do output_file.bat I receive an error, and it won't let me write out to it.
What I would like written in the batch files.
Creating a BAT file for python script
Is there any documentation on how to write out other kinds of files with python? I would also be interested in having a python script generate .c files as well.

Try this, using os.path.join(). Your error was merely trivial, don't worry.
import os
directory = 'C:/'
with open(os.path.join(directory, 'output_file.bat'), 'w') as OPATH:
OPATH.writelines(['#echo off',
'c:\python27\python.exe c:\somescript.py %*',
'pause'])
This provides a cross-platform solution to your problem. Although your error was due to a missing /, you should not hardcode this. This is the best way to join two paths and thus solve your problem.

Related

Python command to execute non-Python (MQL5) files?

I have a collection of expert advisor (EA) scripts written in the MQL5 programming language for the stock/forex trading platform, MetaTrader5. The extension of these files is mq5. I am looking for a way to programatically run these MQL5 files from my Python script on a regular basis. The EAs do some price transformations, eventually saving a set of csv files that will later be read by my Python script to apply Machine Learning models on them.
My first natural choice was the Python API for MetaTrader5. However, according to its documentation, it "is designed for convenient and fast obtaining of exchange data via interprocessor communication directly from the MetaTrader 5 terminal" and as such, it doesn't provide the functionality I need to be able to run MQL scripts using Python.
I have found some posts here on SO (such as #1, #2) about executing non-python files using Python but those posts seemed to always come with the precondition that they already had Python code written in them, only the extension differed - this is different from my goal.
I then came across Python's subprocess module and started experimenting with that.
print(os.path.isfile(os.path.join("path/to/dir","RSIcalc.mq5")))
with open(os.path.join("path/to/dir","RSIcalc.mq5")) as f:
subprocess.run([r"C:\Program Files\MetaTrader 5\terminal64.exe", f], capture_output=True)
The print statement returns True, so the mq5 file exists in the specified location. Then the code opens the MetaTrader5 terminal but nothing else happens, the EA doesn't get executed, process finishes immediately after that.
Am I even on the right track for what I'm trying to achieve here? If yes, what might be the solution for me to run these MQL5 scripts programatically from Python?
Edit:
I use Windows 10 64-bit.
subprocess is indeed the right module for what you want to achieve. But let's look at what you're doing here:
with open(os.path.join("path/to/dir","RSIcalc.mq5")) as f
You're creating a file descriptor handle called f, which is used to write or read contents from a file. If you do print(f) you'll see that it's a python object, that converted to string looks like <_io.TextIOWrapper name='RSIcalc.mq5' mode='r' encoding='UTF-8'>. It is extremely unlikely that such a string is what you want to pass as a command-line parameter to your terminal executable, which is what happens when you include it in your call to subprocess.run().
What you likely want to do is this:
full_path = os.path.abspath(os.path.join("path/to/dir","RSIcalc.mq5"))
result = subprocess.run([r"C:\Program Files\MetaTrader 5\terminal64.exe", full_path], capture_output=True)
Now, this assumes your terminal64 can execute arbitrary scripts passed as parameters. This may or may not be true - you might need extra parameters like "-f" before passing the file path, or you might have to feed script contents through the stdin pipe (unlikely, on Windows, but who knows). That's for you to figure out, but my code above should probably be your starting point.
I don’t think you need to be passing a file object to your sub process statement. In my experience. A program will run a file when the path to the file is provided as a command line argument. Try this:
subprocess.run([r"C:\\Program Files\\MetaTrader 5\\terminal64.exe", os.path.join(“path/to/dir”, “RSIcalc.mq5”], capture_output=True)
This is the same as typing C:\Program Files\MetaTrader 5\terminal64.exe path\to\dir\RSIcalc.mq5 in your terminal.

How to extract zip files with multi parts using python script to run in Google Cloud Function

Good day,
I am very new on python language and I was assigned to build a python script that will get all the attachment files from emails. The attachment files had a multi-disk part (.zip,.z01,.z02,etc). A normal zip file without any multi-disk part can easily be extracted using zipfile module. This codes works:
password = get_data()
files = [f for f in os.listdir(source_file_name) if isfile(join(source_file_name, f))]
for file in files:
if file.endswith('.zip'):
file_name_split = file.split("_")
resource_name = file_name_split[0]
pswd = password[resource_name]
if resource_name not in listdir('extracted/'):
zip_ref = zipfile.ZipFile('attachments/' +file)
zip_ref.setpassword(pwd = bytes(pswd, 'utf-8'))
zip_ref.extractall('extracted')
zip_ref.close()
os.unlink(source_file_name + file)
But I cannot use that code in a multi-disk file because the zip file module does not support ZIP files with appended comments, or multi-disk ZIP files as the documents said on Zip file module.
I search in google for alternatives and I come up using a 7z application by using the python subprocess module.
Here`s my code on this.
zip_exe = '"C:/Program Files/7-Zip/7z.exe"' + ' x ' '"' + tmp_folder + 'sample.zip' '"'
subprocess.Popen(zip_exe, shell = True, cwd = tmp_extracted_folder)
This works at my local using my desktop Windows 10 without any problems. But I was wondering, how can I put this script on Google cloud function? Im not sure that this will work easily by just putting on this script. Do I need to install 7z application on cloud function? Im not sure. Do you guys have any idea if this will work? I need help, I`m getting stuck on this application.
If there`s another way to workaround please let me know. Thank you in advance.
You cannot install a software on Cloud Functions because they do not allow you to interact at the server level, since it is a serverless platform that only executes single purpose functions triggered by events.
If you choose to go with the approach of using the 7zip application you would have to create a server instance for your application using compute engine, however, this would generate server costs for your project and I don't think it's the best solution for your problem.
What you could do is use different Python Libraries than ZipFile to unzip them programatically, which would run in a Cloud Function. Personally I would suggest you to use pyunpack, as it is the most complete unzipping library I found for Python. You can take a look at the documentation for it in this link with instructions on how to implement it and examples, you could also try libarchive and lmza (depending on your python version).
NOTE: For pyunpack, you also need to import patool, which is the "engine" it uses to unpack the files, otherwise it would only rely on ZipFile and it would not work.
Hope This helps.

How do I use subprocess to delete a file in a zip folder using Python

[Python 2.6.5] Simple question but can't seem to find any documentation or previous questions answering my problem. I'm trying to delete 2 files within a ZIP Folder (Its 2 Folders deep in the ZIP Folder if that matters). I want to use subprocess to call 7Zip to delete the files but have no clue how to even start that process. As of now I can only open the application. Ideally, I'd like to run the python script, have the file names hard coded into the script, and have 7zip just automatically delete those files without the application ever opening if possible.
What I have so far:
import subprocess, os
rawLocation = 'SomeLocation\7-ZipPortable.exe'
subprocess.Popen([rawLocation])
This successfully opens the application, but I'd like to run and have it automatically delete files without even opening up if possible.
Note: Thanks for the help everyone. The customer's requirements ended up changing so I don't need to use this logic anymore.
You need to use the command line version of 7zip. And then according to this documentation, you should be able to delete files like so.
7z d archive.zip deleteme.ext
Note: for anyone who might think that Python's zipfile module would be a good solution, I looked through the module, and it doesn't look like it supports deleting files from an archive.
something like this :
from subprocess import call
delete_me = "note.txt"
zip_file = "archive.zip"
try:
call(['7z d', zip_file, delete_me])
except OSError:
# handle errors here
pass

Geany and other IDE not writing to file

I'm using Geany as my editor and when I first started using it, writing to files worked fine but somehow it randomly stopped working. The code executes without any errors but the file isn't created / is empty if already created and I've no idea why.
Simple code as below doesn't work:
filename = 'dogs'
with open(filename, 'w') as f:
f.write('tester')
with open(filename, 'r') as f:
contents = f.read()
print(contents)
The output I get from the 'read' method looks correct on the console output (it just prints 'tester'), but no file is created / edited in my directory.
Geany also has a weirdly complex debugger (if anyone has any helpful guides on how to use it please let me know) so I can't debug properly. I've tried all that I know including using an absolute file path, running in admin mode. The issue is also present when I try to use Pygal to render_to_file(), which is the project I'm working on so right now I can't go any further because anything that requires writing doesn't work. FYI it reads fine.... It's like Geany doesn't have admin rights or something?
EDIT: I've run this code on a python shell (without a .py file) and it worked fine, creating the file as desired. I then ran it using CMD with the .py file and it didn't work. Also ran using Pycharm, it doesn't work when I run it normal but it works when I run it in debug mode? It doesn't seem to be a Geany specific issue, but I am so confused!
Because the code works in the shell I strongly suspect the file is being created somewhere but you are looking in the wrong place.
I know you mentioned absolute paths but I just want to reiterate that you are not currently using an absolute path. An absolute path must start with a '/' (linux/mac) or something like: 'C:/' (windows).
Here are 2 things to try:
1)
Change the name 'dogs' to something really obscure and then do a global search on your whole hard disk for that name. You'll probably find it.
2) Get python to tell you where the file is like this:
import os
filename = 'dogs'
with open(filename, 'w') as f:
f.write('tester')
print(os.path.realpath(f.name))
Got the solution - the files were being created the whole time every time I ran my code, however my antivirus software Comodo contained them within a hidden folder in my drive which couldn't be found by a normal search.
I'm not sure if this a common problem with AV software or just Comodo, can't find anything on the net about it but there you go. I removed these files and the programs from its radar and it now works perfectly.
Although one mystery is how the python shell bypassed that problem. That threw me off thinking it was AV.

Accessing a network folder through a python program

Just a brief outline of what I'm doing: I'm trying to automate some pdf merging routine with python in a network directory, which involves copying, deleting and creating files at a specific network location. Apologies if my language is not very precise.
I'm coding on windows 7, using python 3.6. The program will need to be distributed on other machines, so local and temporary fixes will probably not help. The code I wrote is fully functional and works fine with all the local folders and files, however, now that I need to make use of it on the network, I am having some difficulties accessing the folder I need.
Here is what I have tried:
os.system("pushd " + "\\" + "\\netWorkDrive\Reports")
check_output("pushd " + "\\" + "\\netWorkDrive\Reports", shell=True)
pushd and popd work fine when entered just in the cmd, but when I do system calls through python, they just don't go through. I send a system call, and it runs correctly, but then when I "cd" a current directory, it shows that I'm still in my previous one. If done through the cmd manually, everything works as desired. I have googled the issue, but did not end up finding anything working/useful. I would really appreciate any suggestions, and let me know if I need to clarify my problem further.
Thank you!
I would not use pushd/popd in such a way, I would just include the full paths, including network paths in the paths of whatever file operation I need to do
However if I really need to change working directory, I would do this with python:
import os
original_working_directory = os.getcwd()
# do stuff
new_networked_directory = r'\\server\share\folder'
# change to the networked directory
os.chdir(new_networked_directory)
# do stuff
#changeback to original working directory
os.chdir(original_working_directory)
# do more stuff
There should be no need for "temp drives" or the like really.

Categories