Trying to understand win32api, win32con - python [duplicate] - python

So, I'm trying to make myself a Python script which goes through the selected Music folder and tells the user if specific album doesn't have an album cover. It basically goes through all the files and checks if file[-4:] in (".jpg",".bmp",".png"), if true, it found a picture file. Just to make it clear, the structure of my folders is:
Music folder
Arctic Monkeys
Humbug (2009)
Suck it and see (2011)
Morphine
Cure For Pain (1993)
.. and so on. I'm testing the script to find if there's a missing cover in my Arctic Monkeys directory, and my script goes through the "Humbug (2009)" folder and finds AlbumArtSmall.jpg which doesn't show up in the command prompt so I tried "Show hidden files/folders" and still nothing. However, the files show up once I uncheck "Hide protected operating system files", so that's kinda weird.
My question is - how do I tell Python to skip searching the hidden/protected files?
I checked out the How to ignore hidden files using os.listdir()? but the solution I found there only works for files starting with ".", and that's not what I need.
Cheers!
Edit - so here's the code:
import os
def findCover(path, band, album):
print os.path.join(path, band, album)
coverFound = False
for mFile in os.listdir(os.path.join(path, band, album)):
if mFile[-4:] in (".jpg",".bmp",".png"):
print "Cover file found - %s." % mFile
coverFound = True
return coverFound
musicFolder = "E:\Music" #for example
noCovers = []
for band in os.listdir(musicFolder): #iterate over bands inside the music folder
if band[0:] == "Arctic Monkeys": #only Arctic Monkeys
print band
bandFolder = os.path.join(musicFolder, band)
for album in os.listdir(bandFolder):
if os.path.isdir(os.path.join(bandFolder,album)):
if findCover(musicFolder, band, album): #if cover found
pass #do nothing
else:
print "Cover not found"
noCovers.append(band+" - "+album) #append to list
else: #if bandFolder is not actually a folder
pass
print ""

You can use with the pywin32 module, and manually test for FILE_ATTRIBUTE_HIDDEN or any number of attributes
FILE_ATTRIBUTE_ARCHIVE = 32
FILE_ATTRIBUTE_ATOMIC_WRITE = 512
FILE_ATTRIBUTE_COMPRESSED = 2048
FILE_ATTRIBUTE_DEVICE = 64
FILE_ATTRIBUTE_DIRECTORY = 16
FILE_ATTRIBUTE_ENCRYPTED = 16384
FILE_ATTRIBUTE_HIDDEN = 2
FILE_ATTRIBUTE_NORMAL = 128
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192
FILE_ATTRIBUTE_OFFLINE = 4096
FILE_ATTRIBUTE_READONLY = 1
FILE_ATTRIBUTE_REPARSE_POINT = 1024
FILE_ATTRIBUTE_SPARSE_FILE = 512
FILE_ATTRIBUTE_SYSTEM = 4
FILE_ATTRIBUTE_TEMPORARY = 256
FILE_ATTRIBUTE_VIRTUAL = 65536
FILE_ATTRIBUTE_XACTION_WRITE = 1024
like so:
import win32api, win32con
#test for a certain type of attribute
attribute = win32api.GetFileAttributes(filepath)
#The file attributes are bitflags, so you want to see if a given flag is 1.
# (AKA if it can fit inside the binary number or not)
# 38 in binary is 100110 which means that 2, 4 and 32 are 'enabled', so we're checking for that
## Thanks to Nneoneo
if attribute & (win32con.FILE_ATTRIBUTE_HIDDEN | win32con.FILE_ATTRIBUTE_SYSTEM):
raise Exception("hidden file") #or whatever
#or alter them
win32api.SetFileAttributes(filepath, win32con.FILE_ATTRIBUTE_NORMAL) #or FILE_ATTRIBUTE_HIDDEN
After you alter a file, take a look in the folder, it won't be hidden anymore.
Found this information here and here: Checking file attributes in python
Alternatively, you can try to use the os.stat function, whose docs here and then use the stat module to further understand what you're looking at.
Found these relevant questions. (python) meaning of st_mode and How can I get a file's permission mask?

Related

self.zone.locations==None when parsing zones.mpk

I've finally made it through all of the linting errors when I converted the project from the archaic Python 2.7 code to Python 3.11. When I run python MapperGUI-3.pyw, the GUI loads but something is keeping the daoc game path from being loaded properly and stored, resulting in the error message "Game not found".
I've beat my ahead against the functions and variables and I am sure I'm missing something obvious, but for the life of me I cannot figure out where it is going wrong parsing the game directory of 'C:/Program Files (x86)/Electronic Arts/Dark Age of Camelot/'
For whatever reason, the program is stuck thinking self.zone.locations==None and I confirmed this by manually declaring the variable to a valid one and things worked fine.
MapperGUI/modules/zones.py is the module that loads the zones from the .mpk file dynamically. I verified mapper/all_locations.txt is being created properly when zones.py is parsed and called from the main program.
Did I miss something in zones.py? When I ran the 2 to 3 conversion on it, nothing was changed and I am not seeing any runtime errors.
#zones.py
import os, sys
sys.path.append("../mapper")
import dempak
import datParser as ConfigParser
class Zones:
def __init__(self, gamepath):
try:
self.locations=[]
cp=ConfigParser.ConfigParser()
cp.readfp(dempak.getMPAKEntry(os.path.join(gamepath, 'zones', 'zones.mpk'), 'zones.dat'))
sections=cp.sections()
sections.sort()
for s in sections:
if s[:4] == 'zone':
id=int(s[4:])
enabled=int(cp.get(s, 'enabled'))
name=cp.get(s, 'name')
region=cp.get(s,'region'); # need region to id realm -- cch
try:
type=int(cp.get(s, 'type'))
except ConfigParser.NoOptionError:
type=0
if type==0 or type==3:
# add region to tuple -- cch
self.locations.append(("%03d" % id, name, region))
else: # ignore type 1,2,4 (city,dungeon,TOA city)
continue
dataFile=open("mapper/all_locations.txt","w")
for x in range(len(self.locations)):
dataFile.write("%s : %s\n" % (self.locations[x][0], self.locations[x][1]))
dataFile.close()
except IOError:
self.locations=None

How to change VLC-python output device?

In my project, I need to get sound from a radio stream URL and play it. But it needs to be played in a specific output device called "VB-Cable Input (Virtual Audio Cable)".
I couldn't find a way to do it. This is my current code:
import vlc
import time
url = "https://shout25.crossradio.com.br:18156/1"
# Create VLC instance, media player and media
instance = vlc.Instance()
player = instance.media_player_new()
media = instance.media_new(url)
player.set_media(media)
# Get list of output devices
def get_device():
mods = player.audio_output_device_enum()
if mods:
mod = mods
while mod:
mod = mod.contents
# If VB-Cable is found, return it's module and device id
if 'CABLE Input (VB-Audio Virtual Cable)' in str(mod.description):
device = mod.device
module = mod.description
return device,module
mod = mod.next
# Sets the module and device id to VB-Cable
device,module = get_device()
# Sets VB-Cable as output device
player.audio_output_device_set(device,module)
# Trying the function #Random Davis stated, but results still the same
vlc.libvlc_audio_output_device_set(player, module, device)
# It should return VB-Cable as current audio output, but None is returned...
print(player.audio_output_device_get())
# Audio plays in default output device, which is incorrect
player.play()
time.sleep(60)
I searched through StackOverflow and the VLC documentation, but couldn't get the result I expected, I believe I'm using the functions in the wrong way.
After some research, I found this implementation of audio_output_device_set() in GitHub
As #RandomDavis said, the problem was indeed in this function. All I had to do was switching the first argument to None and leave the rest as it is.
This is the correct code:
# Sets VB-Cable as output device
player.audio_output_device_set(None, device)
Still not quite sure why inserting any values other than None makes the function invalid. But the problem is now solved.

python importlib seems to be sharing data between instances

Ok, so I am having a weird one. I am running python in a SideFX Hython (their custom build) implementation that is using PDG. The only real difference between Hython and vanilla Python is some internal functions for handling geometry data and compiled nodes, which shouldn't be an issue even though they are being used.
The way the code runs, I am generating a list of files from the disk which creates PDG work items. Those work items are then processed in parallel by PDG. Here is the code for that:
import importlib.util
import pdg
import os
from pdg.processor import PyProcessor
import json
class CustomProcessor(PyProcessor):
def __init__(self, node):
PyProcessor.__init__(self,node)
self.extractor_module = 'GeoExtractor'
def onGenerate(self, item_holder, upstream_items, generation_type):
for upstream_item in upstream_items:
new_item = item_holder.addWorkItem(parent=upstream_item, inProcess=True)
return pdg.result.Success
def onCookTask(self, work_item):
spec = importlib.util.spec_from_file_location("callback", "Geo2Custom.py")
GE = importlib.util.module_from_spec(spec)
spec.loader.exec_module(GE)
GE.convert(f"{work_item.attribValue('directory')}/{work_item.attribValue('filename')}{work_item.attribValue('extension')}", work_item.index, f'FRAME { work_item.index }', self.extractor_module)
return pdg.result.Success
def bulk_convert (path_pattern, extractor_module = 'GeoExtractor'):
type_registry = pdg.TypeRegistry.types()
try:
type_registry.registerNode(CustomProcessor, pdg.nodeType.Processor, name="customprocessor", label="Custom Processor", category="Custom")
except Exception:
pass
whereItWorks = pdg.GraphContext("testBed")
whatWorks = whereItWorks.addScheduler("localscheduler")
whatWorks.setWorkingDir(os.getcwd (), '$HIP')
whereItWorks.setValues(f'{whatWorks.name}', {'maxprocsmenu':-1, 'tempdirmenu':0, 'verbose':1})
findem = whereItWorks.addNode("filepattern")
whereItWorks.setValue(f'{findem.name}', 'pattern', path_pattern, 0)
generic = whereItWorks.addNode("genericgenerator")
whereItWorks.setValue(generic.name, 'itemcount', 4, 0)
custom = whereItWorks.addNode("customprocessor")
custom.extractor_module = extractor_module
node1 = [findem]
node2 = [custom]*len(node1)
for n1, n2 in zip(node1, node2):
whereItWorks.connect(f'{n1.name}.output', f'{n2.name}.input')
n2.cook(True)
for node in whereItWorks.graph.nodes():
node.dirty(False)
whereItWorks.disconnect(f'{n1.name}.output', f'{n2.name}.input')
print ("FULLY DONE")
import os
import hou
import traceback
import CustomWriter
import importlib
def convert (filename, frame_id, marker, extractor_module = 'GeoExtractor'):
Extractor = importlib.__import__ (extractor_module)
base, ext = os.path.splitext (filename)
if ext == '.sc':
base = os.path.splitext (base)[0]
dest_file = base + ".custom"
geo = hou.Geometry ()
geo.loadFromFile (filename)
try:
frame = Extractor.extract_geometry (geo, frame_id)
except Exception as e:
print (f'F{ frame_id } Geometry extraction failed: { traceback.format_exc () }.')
return None
print (f'F{ frame_id } Geometry extracted. Writing file { dest_file }.')
try:
CustomWriter.write_frame (frame, dest_file)
except Exception as e:
print (f'F{ frame_id } writing failed: { e }.')
print (marker + " SUCCESS")
The onCookTask code is run when the work item is processed.
Inside of the GeoExtractor.py program I am importing the geometry file defined by the work item, then converting it into a couple Pandas dataframes to collate and process the massive volumes of data quickly, which is then passed to a custom set of functions for writing binary files to disk from the Pandas data.
Everything appears to run flawlessly, until I check my output binaries and see that they escalate in file size much more than they should, indicating that either something is being shared between instances or not cleared from memory and subsequent loads of the extractor code is appending the dataframes which are named the same.
I have run the GeoExtractor code sequentially with the python instance closing between each file conversion using the exact same code and the files are fine, growing only very slowly as the geometry data volume grows, so the issue has to lie somewhere in the parallelization of it using PDG and calling the GeoExtractor.py code over and over for each work item.
I have contemplated moving the importlib stuff to the __init__() for the class leaving only the call to the member function in the onCookTask() function. Maybe even going so far as to pass a unique variable for each work item which is used inside GeoExtractor to create a closure of the internal functions so they are unique instances in memory.
I tried to do a stripped down version of GeoExtractor and since I'm not sure where the leak is, I just ended up pulling out comments with proprietary or superfluous information and changing some custom library names, but the file ended up kinda long so I am including a pastebin: https://pastebin.com/4HHS8D2W
As for CustomGeometry and CustomWriter, there is no working form of either of those libraries that will be NDA safe, so unfortunately they have to stay blackboxed. The CustomGeometry is a handful of container classes which organize all of the data coming out of the geometry, and the writer is a formatter/writer for the binary format we are utilizing. I am hoping the issue wouldn't be in either of them.
Edit 1: I fixed an issue in the example code.
Edit 2: Added larger examples.

Python, returning data collected in npyscreen

So I'm creating a basic TUI for a script I created. The goal is to collect several variables that include paths to directories and files. What I'm not sure about is once I've created the visual aspect of it, how to get those pieces of information to interact with other parts of the code.
Below is what I have so far in terms of the visual portion (the other part is about 500 lines), and honestly I'm at a loss on how to even print any of the variables set under the class and any pointers would be greatly appreciated.
#!/usr/bin/env python
# encoding: utf-8
import npyscreen
class PlistCreator(npyscreen.NPSApp):
def main(self):
screen = npyscreen.Form(name="Welcome to Nicks Playlist Creator!")
plistName = screen.add(npyscreen.TitleText, name="Playlist Name:" )
csvPath = screen.add(npyscreen.TitleFilenameCombo, name="CSV Schedule:")
toaPath = screen.add(npyscreen.TitleFilenameCombo, name="Path to ToA Video Folder:", use_two_lines=True)
outputPath = screen.add(npyscreen.TitleFilenameCombo, name = "Output Folder:", use_two_lines=True)
dateOfAir = screen.add(npyscreen.TitleDateCombo, name="Date of Air:")
timeOfStart = screen.add(npyscreen.TitleText, name="Time of Air (TC):")
screen.edit()
if __name__ == "__main__":
App = PlistCreator()
App.run()
You can get the value of any form object using the dit notation.
plistName = screen.add(npyscreen.TitleText, name="Playlist Name:" )
playlist_name = self.screen.plistName.value
etc. Note there are no parentheses after value. Once you have it in a variable, you can build another method in the class to handle the information.

I need a super-duper simple CGI Python photo upload

I've looked through tons of answers but the truth is, I only know super basic python and I really need help. I don't know the os module or anything like that and I can't use PHP (not that I know it anyway, but it's not permitted) and I need something so easy that I can understand it.
Basically, I need a CGI upload (I don't need the HTML form, I've got that much down) that will take the photo and save it. That's it. I don't need any fancy place for it to save, I just need the file to be properly uploaded from the form.
I've got various versions of this function and I can't get them working because I don't understand them so PLEASE HELP!!!
import cgi
def savefile (filename, photodoc):
form=cgi.FieldStorage()
name=form[filename]
period=name.split(.)
if period[1]=="jpeg" or period[1]=="jpg" or period[1]=="png":
idk what to do
else:
make an error message
This cgi program will "take the photo and save it. That's it."
#!/usr/bin/python2.7
import cgi
field=cgi.FieldStorage()['fieldname']
open(field.filename, 'wb').write(field.value)
Among the things it doesn't do are error checking and security checking, and specifying in what directory the files should be saved.
Duplicate question but here's what you need:
Depending if windows or linux, first set to binary mode:
try:
import msvcrt
msvcrt.setmode (0, os.O_BINARY)
msvcrt.setmode (1, os.O_BINARY)
except ImportError:
pass
Then:
form = cgi.FieldStorage()
name = form[filename]
period = name.split('.') #You need the quotes around the period
if period[1]=='jpeg' or period[1] == 'jpg' or period[1] =='png':
if upload.filename:
name = os.path.basename(upload.filename)
out = open(YOUR_FILEPATH_HERE + name, 'wb', 1000)
message = "The file '" + name + "' was uploaded successfully"
while True:
packet = upload.file.read(1000)
if not packet:
break
out.write(packet)
out.close()
else:
print 'Error'
Some sources:
How to use Python/CGI for file uploading
http://code.activestate.com/recipes/273844-minimal-http-upload-cgi/

Categories