Beginner Python Project - My function is skipping, what is causing this? - python-3.x

as the title says I'm a beginner with Python. I have started to work on what I thought first was a simple enough script for scanning a folder and printing the names of each subdirectory to a CMD prompt.
However, I've run into an issue where the function in the code below does not execute. I suspect it's to do with Windows permissions which is why I've added in the is_admin(): function.
My question is, what is it that is causing the function to skip? and what is the proper way to achieve what it is I am trying to do?
Any and all help is appreciated and if anyone could point me in the direction for learning more about Python and the Windows OS technical side for programmers would be doing me a huge favor.
Thanks in advance :)
import os, sys, ctypes
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
if is_admin():
rootdir = 'C:/Windows'
def listdirs(rootdir):
for file in os.listdir(rootdir):
d = os.path.join(rootdir, file)
if os.path.isdir(d):
print(d)
listdirs(d)
listdirs(rootdir)
else:
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv\[1:\]), None, 1)
input('Press any key to continue...')
Expecting the program to:
Produce an output of all the subdirectories of a folder printed to a CMD prompt window and have the window stay open when the program has finished executing each line of code. The Window should remain open until the user is finished with it. The Windows UAC should prompt asking the user if they wish to run as admin, if the user is already an admin then it should skip this and proceed to run the program.

Related

Issue with Python tkinter / pypdftk / subprocess(?)

I have been using this whole script flawlessly on my PC. I attempted to put it on my coworkers PC, but this particular part doesn't seem to work. I am using a tkinter interface to take data from psql and fill a premade fillable PDF using pypdftk, then either saving it using asksaveasfilename and opening it with subprocess.Popen or not saving it and opening it as a temp file using subprocess.run. On my PC both work great. On coworkers PC, neither work.
On my coworkers PC, the save option opens the save dialog with all the correct info as far as I can tell, and lets me go through the process of saving a file as it normally would, but then the file just doesn't save and never actually appears. If I open as a temp file, it throws the exception.
import tkinter as tk
from tkinter import *
from tkinter.ttk import *
import tkinter.messagebox
import pypdftk
from tkinter.filedialog import asksaveasfilename
import os.path
import os
import subprocess
from pathlib import Path
def file_handler(form_path, data, fname):
try:
tl2 = tk.Toplevel()
tl2.wm_title('File Handler')
w = 340
h = 55
ws = tl2.winfo_screenwidth()
hs = tl2.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
tl2.geometry('%dx%d+%d+%d' % (w, h, x, y))
def save_and_open():
savefile = asksaveasfilename(defaultextension=".pdf", initialdir="C:\\Desktop", filetypes=[('pdf file', '*.pdf')], initialfile=fname)
generated_pdf = pypdftk.fill_form(form_path, data, savefile)
subprocess.Popen(generated_pdf,shell=True)
def open_without_save():
try:
generated_pdf = pypdftk.fill_form(form_path, data)
os.rename(generated_pdf, generated_pdf+".pdf")
generated_pdf = generated_pdf+".pdf"
subprocess.run(generated_pdf,shell=True)
except:
tk.messagebox.showerror("Unable to open", "An error has occurred. Please try again.")
else:
tl2.destroy()
finally:
if os.path.exists(generated_pdf):
os.remove(generated_pdf)
print("Successfully removed temp file.")
save = tk.Button(tl2,text='Save and Open', width=20, command=save_and_open)
nosave = tk.Button(tl2,text='Open without saving', width=20,command=open_without_save)
save.grid(row=0, columnspan=2, sticky='NESW', padx=5, pady=10, ipadx=5, ipady=5)
nosave.grid(row=0, column=2, columnspan=2, sticky='NESW', padx=5, pady=10, ipadx=5, ipady=5)
tl2.mainloop()
except:
tk.messagebox.showerror("Unable to open", "An error has occurred. Please try again.")
As far as I can tell, everything works until you get into the save_and_open and open_without_save functions. I left in all the libraries I believe are relevant.
I should also mention, I am quite a novice at python. So if any of this is ugly coding, feel free to shame me for it.
update:
I now believe the problem to be here in the pypdftk.py file:
if os.getenv('PDFTK_PATH'):
PDFTK_PATH = os.getenv('PDFTK_PATH')
else:
PDFTK_PATH = '/usr/bin/pdftk'
if not os.path.isfile(PDFTK_PATH):
PDFTK_PATH = 'pdftk'
My error states pdftk is not a known command. My guess is that there is no environment variable, then it looks to the /usr/bin and cannot find the pdftk file, so it's just making "pdftk" a string? I don't know much about /usr/bin, but is there a way to check that?
What's going on in lines 19-21
if os.getenv('PDFTK_PATH'): is checking to see if the environment variable PDFTK_PATH even exists on your machine. If so, the constant PDFTK_PATH is set to the value provided by the PDFTK_PATH environment key/variable.
Otherwise, it sets PDFTK_PATH to /usr/bin/pdftk. Two things are happening here... First, it provides a path to the binary, i.e., /usr/bin. Second, it provides the name of the binary, i.e., pdftk. In other words, it sets PDFTK_PATH to path + executable filename.
(NOTE: The directory usr/bin is where most executables are stored on machines running Unix-like operating systems, e.g., Mac, Ubuntu, etc. This is alluded to in the repo, see here.)
To err on the side of caution, if not os.path.isfile(PDFTK_PATH): checks to see if the pdftk binary can indeed be found in the /usr/bin/ folder. If not, it sets PDFTK_PATH to pdftk, i.e., it sets the path to the pdftk binary to the very directory in which pypdftk.py is located.
Farther down, the try block runs a test call on whatever the value of PDFTK_PATH was ultimately set to. See lines 46-49. If the binary, pdftk.exe, is not where PDFTK_PATH says it is, then you get the error that you got.
Concerning the r-string
As for casting the string literal to an r-string, that actually did nothing. The r prefix simply redefines the \ as just that, a backslash, rather than allowing the \ to continue to function as cue to an escape sequence. See here and here. You'll notice that neither /usr/bin/pdftk nor pdftk, i.e., where you prepended the r, contain any backslashes.
What I think happened...
After you took the advice of acw1668, and installed the PDF Toolkit (pdftk); and reinstalled the pypdftk package, you had probably fixed the problem. I don't know, but maybe you had not restarted your IDE/editor during these steps? (Side note: Sometimes you need to restart your IDE/editor after changes have been made to your machine's environment variables/settings.)
The short answer: If you're on a windows machine, the install of the pdftk toolkit added PDFTK_PATH to your environment; or, if you're on a Unix-based machine, the install placed the binary in the /usr/bin directory.
Regardless, I assure you the r had nothing to do with it. Now that you know it's working, let's prove it... take out the r, you'll see that it is still working.
I was able to fix this problem by going into the pypdftk.py file and changing the paths to raw strings like such:
if os.getenv('PDFTK_PATH'):
PDFTK_PATH = os.getenv('PDFTK_PATH')
else:
PDFTK_PATH = r'/usr/bin/pdftk'
if not os.path.isfile(PDFTK_PATH):
PDFTK_PATH = r'pdftk'

requests.get(url).headers.get('content-disposition') returning NONE on PYTHON

Well, I've got the need of automate a process in my job(actually I'm an intern), and I just wondered if I could use Python for such process. I'm still processing my ideas of how to do those stuffs, and now I'm currently trying to understand how to download a file from a web URL using python3. I've found a guide on another website, but there's no active help there. I was told to use the module requests to download the actual file, and the module re to get the real file name.
The code was working fine, but then I tried to add some features like GUI, and it just stopped working. I took off the GUI code, and it didn't work again. Now I have no idea of what to do to get the code working, pls someone helo me, thanks :)
code:
import os
import re
# i have no idea of how this function works, but it gets the real file name
def getFilename(cd):
if not cd:
print("check 1")
return None
fname = re.findall('filename=(.+)', cd)
if len(fname) == 0:
print("check 2")
return None
return fname[0]
def download(url):
# get request
response = requests.get(url)
# get the real file name, cut off the quota and take the second element of the list(actual file name)
filename = getFilename(response.headers.get('content-disposition'))
print(filename)
# open in binary mode and write to file
#open(filename, "wb").write(response.content)
download("https://pixabay.com/get/57e9d14b4957a414f6da8c7dda353678153fd9e75b50704b_1280.png?attachment=")
os.system("pause")```

PYTHON rumps program stops responding after subprocess calls another script

I am currently working on a project that contains many system tray utilities on mac osx, one of these utilities is a 'fake friend soundboard' where I am to enable the user to click on the module then select as example "Discord Ping x1" and the program playback a soundfile of the ping.
Im using RUMPS which enables me to add menus to the system tray however when trying to use libraries to play sounds directly through upon the #rumps.clicked, nothing seems to happen
Instead I've programmed it to run another script that can easily play the sound inside another folder containing all the sounds.
When running the script and clicking a sound, it plays the sound exactly as intended,
but then the program stops responding...
Is this something I'm doing wrong with my code or is there another way i could play the sound using this library?
Heres the code:
import rumps
import subprocess
class sound(rumps.App):
def __init__(self):
super(sound, self).__init__("🔊")
self.menu = ["Fake friend soundboard",
None,
"Discord Sounds:",
"Ping x1",
"Incoming Call",
"Enter Call",
"Leave Call",
"Mute",
"Deafen",
None,
"Skype Sounds:",
"Incoming Call",
None,
"Random:",
"okbuddyretard",
None]
#rumps.clicked("Ping x1")
def about(sender):
subprocess.run("python3 soundboard/discord_pingx1.py", shell=True)
if __name__ == "__main__":
sound().run()
In the soundboard folder there is the sounds folder containing the discord folder containing **
discord_ping.wav
The soundboard folder also hold the discordd_pingx1.py script which is below.
import pyglet
def sound():
sound = pyglet.resource.media('sounds/discord/discord_ping.wav', streaming=False)
sound.play()
pyglet.app.run()
sound()
after running my main.py (opens all the modules)
and clicking the sound tab and then clicking the button set to make the sound,
it plays, but then stops responding.
Any help at all would be much appreciated.
I highly recommend avoiding the insert of subprocess or sys-calls inside of a Python script that executes Objective-C code. This leads to Aborts and Traps. Instead, refer to Apple's APIs and utilize AppleScript (osascript).
Here is a better implementation that calls a script to call your script from osascript:
exec.py
import platform
import subprocess, sys, os
applescript = '''\
do shell script "bash /path/to/file/myShellScript.sh"\
'''
# parse and stdout
args = [item for x in [("-e",l.strip()) for l in applescript.split('\n') if l.strip() != ''] for item in x]
proc = subprocess.Popen(["osascript"] + args ,stdout=subprocess.PIPE )
progname = proc.stdout.read().strip()
sys.stdout.write(str(progname))
The parser takes the string with the osascript in it and parses it for a stdout write. Stdout writes are very safe, considering they are handling data from the same thread.
/path/to/file/myShellScript.sh (add the shebang on line 1 as well)
#!/bin/bash
python3 soundboard/discord_pingx1.py
This 100% handles your problem without causing subprocess errors. If you get hung with subprocess, your computer will continue running Python3. If the Application doesn't stop freezing, exit the app by cmd+Space and typing Activity Monitor. Then, find Python3 by cmd+f and typing python3. Click it and press Quit in the top left corner (the X or stop-light symbol).

Running console window in background for GUI using tkinter on Windows 10

So I have this GUI that I made with tkinter and everything works well. What it does is connects to servers and sends commands for both Linux or Windows. I went ahead and used pyinstaller to create a windowed GUI without console and when I try to uses a specific function for sending Windows commands it will fail. If I create the GUI with a console that pops up before the GUI, it works like a charm. What I'm trying to figure out is how to get my GUI to work with the console being invisible to the user.
The part of my code that has the issue revolves around subprocess. To spare you all from the 400+ lines of code I wrote, I'm providing the specific code that has issues. Here is the snippet:
def rcmd_in(server):
import subprocess as sp
for i in command_list:
result = sp.run(['C:/"Path to executable"/rcmd.exe', '\\\\' + server, i],
universal_newlines=True, stdout=sp.PIPE, stderr=sp.STDOUT)
print(result.stdout)
The argument 'server' is passed from another function that calls to 'rcmd_in' and 'command_list' is a mutable list created in the root of the code, accessible for all functions.
Now, I have done my due diligence. I scoured multiple searches and came up with an edit to my code that makes an attempt to run my code with that console invisible, found using info from this link: recipe-subprocess. Here is what the edit looks like:
def rcmd_in(server):
import subprocess as sp
import os, os.path
si = sp.STARTUPINFO()
si.dwFlags |= sp.STARTF_USESHOWWINDOW
for i in command_list:
result = sp.run(['C:/"Path to executable"/rcmd.exe', '\\\\' + server, i],
universal_newlines=True, stdin=sp.PIPE, stdout=sp.PIPE,
stderr=sp.STDOUT, startupinfo=si, env=os.environ)
print(result.stdout)
The the problem I have now is when it runs an error of "Error:8 - Internal error -109" pops up. Let me add I tried using functions 'call()', 'Popen()', and others but only 'run()' seems to work.
I've reached a point where my brain hurts and I can use some help. Any suggestions? As always I am forever great full for anyone's help. Thanks in advance!
I figured it out and it only took me 5 days! :D
Looks like the reason the function would fail falls on how Windows handles stdin. I found a post that helped me edit my code to work with pyinstaller -w (--noconsole). Here is the updated code:
def rcmd_in(server):
import subprocess as sp
si = sp.STARTUPINFO()
si.dwFlags |= sp.STARTF_USESHOWWINDOW
for i in command_list:
result = sp.Popen(['C:/"Path to executable"/rcmd.exe', '\\\\' + server, i],
universal_newlines=True, stdin=sp.PIPE, stdout=sp.PIPE,
stderr=sp.PIPE, startupinfo=si)
print(result.stdout.read())
Note the change of functions 'run()' to 'Popen()'. The 'run()' function will not work with the print statement at the end. Also, for those of you who are curious the 'si' variable I created is preventing 'subprocess' from opening a console when being ran while using a GUI. I hope this will become useful to someone struggling with this. Cheers

The system cannot find the file specified when trying to open a URL in a browser

I get the syntax error:
FileNotFoundError: [WinError 2] The system cannot find the file specified
when running the below code.
It is a little hard to find a good solution for this problem on windows which I am running as compared to UNIX which I can find working code for.
from subprocess import Popen, check_call
p1 = Popen('start http://stackoverflow.com/')
p2 = Popen('start http://www.google.com/')
p3 = Popen('start http://www.facebook.com/')
time.sleep(60)
for pid in [p1.pid,p2.pid,p3.pid]:
check_call(['taskkill', '/F', '/T', '/PID', str(pid)])
I want the code to open the pages for 60 seconds and then close them.
I know there is similar topic on the link:
, but firstly it is for python 2 and I have tried the codes using the subprocess module and they are identical to the code I am using which does not work.
Windows might be thrown off by the slashes in the url. I dont have a windows machine right now but could you try quoting the urls?
It would be nice if you got this working, but the proper python way to do this is to use the webbrowser module. Like this:
import webbrowser
url = "google.com"
webbrowser.open_new_tab(url)
closing these would be more tricky but i think your question is a duplicate of this, with almost exactly the same code and also for windows.
So i think you should search for your answer there first.
How to close an internet tab with cmd/Python?
Replace
p1 = Popen('start http://stackoverflow.com')
with
p1 = Popen('start http://stackoverflow.com',shell=True)
to make sure the command is executed through the shell.
If passing a single string, either shell must be True (see below) or else the string must simply name the program to be executed without specifying any arguments.
Source: https://docs.python.org/3/library/subprocess.html

Resources