I tried to add a new item to an already existing spreadsheet but it doesn't seem to work. However, the file's property matches my timestamp of last recent call in python 3. Because this is a rather larger project, some background information may be necessary for trouble shooting.
I am using Openpyxl 2.5.3
As for now, both files (*.py and *.xlsx) are in the same directory
furthermore, they're currently stored in a OneDrive folder which synchronizes automatically
When trying to run
def add_value(self, to_position: Coordinate, new_value: str or int) -> bool:
try:
string = get_column_letter(to_position[0]) if isinstance(to_position[0], int) else to_position[0]
self.Sheet[f"{string}{to_position[1]}"].value = str(new_value)
workbook.save(self.Fullfilename)
return True
except (FileNotFoundError, IOError) as e:
print(f"{e}\n{filename} couldn't be found in current working directory\n[{os.listdir()}].")
return False
the function evaluates to True but no changes to the files have been made.
Ok, I am really stupid. My __init__ constructor comes with an attribute called self.Workbook. But I misspellt it self.Worbook, which in turn affected self.Sheet = self.WorBook.active. Note that I wrote workbook.save(self.Fullfilename), but I have to save the changes to self.Workbook.save(Fullfilename). As a final note, the *.xlsx's timestamp update in file properties was displayed next to 更新日時 (date of modification) which initially lead to my confusion whether my script accessed or edited the spreadsheet for real.
Related
I'm working on a script that takes a checksum and directory as inputs.
Without too much background, I'm looking for 'malware' (ie. a flag) in a directory of executables. I'm given the SHA512 sum of the 'malware'. I've gotten it to work (I found the flag), but I ran into an issue with the output after generalizing the function for different cryptographic protocols, encodings, and individual files instead of directories:
FileNotFoundError: [Errno 2] No such file or directory : 'lessecho'
There is indeed a file lessecho in the directory, and as it happens, is close to the file that returns the actual flag. Probably a coincidence. Probably.
Below is my Python script:
#!/usr/bin/python3
import hashlib, sys, os
"""
### TO DO ###
Add other encryption techniques
Include file read functionality
"""
def main(to_check = sys.argv[1:]):
dir_to_check = to_check[0]
hash_to_check = to_check[1]
BUF_SIZE = 65536
for f in os.listdir(dir_to_check):
sha256 = hashlib.sha256()
with open(f, 'br') as f: <--- line where the issue occurs
while True:
data = f.read(BUF_SIZE)
if not data:
break
sha256.update(data)
f.close()
if sha256.hexdigest() == hash_to_check:
return f
if __name__ == '__main__':
k = main()
print(k)
Credit to Randall for his answer here
Here are some humble trinkets from my native land in exchange for your wisdom.
Your listdir call is giving you bare filenames (e.g. lessecho), but that is within the dir_to_check directory (which I'll call foo for convenience). To open the file, you need to join those two parts of the path back together, to get a proper path (e.g. foo/lessecho). The os.path.join function does exactly that:
for f in os.listdir(dir_to_check):
sha256 = hashlib.sha256()
with open(os.path.join(dir_to_check, f), 'br') as f: # add os.path.join call here!
...
There are a few other issues in the code, unrelated to your current error. One is that you're using the same variable name f for both the file name (from the loop) and file object (in the with statement). Pick a different name for one of them, since you need both available (because I assume you intend return f to return the filename, not the recently closed file object).
And speaking of the closed file, you're actually closing the file object twice. The first one happens at the end of the with statement (that's why you use with). The second is your manual call to f.close(). You don't need the manual call at all.
I am struggling to get this working.
I tried to transpose from a c++ post into python with no joy:
QMessageBox with a "Do not show this again" checkbox
my rough code goes like:
from PyQt5 import QtWidgets as qtw
...
mb = qtw.QMessageBox
cb = qtw.QCheckBox
# following 3 lines to get over runtime errors
# trying to pass the types it was asking for
# and surely messing up
mb.setCheckBox(mb(), cb())
cb.setText(cb(), "Don't show this message again")
cb.show(cb())
ret = mb.question(self,
'Close application',
'Do you really want to quit?',
mb.Yes | mb.No )
if ret == mb.No:
return
self.close()
the above executes with no errors but the checkbox ain't showing (the message box does).
consider that I am genetically stupid... and slow, very slow.
so please go easy on my learning curve
When trying to "port" code, it's important to know the basis of the source language and have a deeper knowledge of the target.
For instance, taking the first lines of your code and the referenced question:
QCheckBox *cb = new QCheckBox("Okay I understand");
The line above in C++ means that a new object (cb) of type QCheckBox is being created, and it's assigned the result of QCheckBox(...), which returns an instance of that class. To clarify how objects are declared, here's how a simple integer variable is created:
int mynumber = 10
This is because C++, like many languages, requires the object type for its declaration.
In Python, which is a dynamic typing language, this is not required (but it is possible since Python 3.6), but you still need to create the instance, and this is achieved by using the parentheses on the class (which results in calling it and causes both calling __new__ and then __init__). The first two lines of your code then should be:
mb = qtw.QMessageBox()
cb = qtw.QCheckBox()
Then, the problem is that you're calling the other methods with new instances of the above classes everytime.
An instance method (such as setCheckBox) is implicitly called with the instance as first argument, commonly known as self.
checkboxInstance = QCheckBox()
checkboxInstance.setText('My checkbox')
# is actually the result of:
QCheckBox.setText(checkboxInstance, 'My checkbox')
The last line means, more or less: call the setText function of the class QCheckBox, using the instance and the text as its arguments.
In fact, if QCheckBox was an actual python class, setText() would look like this:
class QCheckBox:
def setText(self, text):
self.text = text
When you did cb = qtw.QCheckBox you only created another reference to the class, and everytime you do cb() you create a new instance; the same happens for mb, since you created another reference to the message box class.
The following line:
mb.setCheckBox(mb(), cb())
is the same as:
QMessageBox.setCheckBox(QMessageBox(), QCheckBox())
Since you're creating new instances every time, the result is absolutely nothing: there's no reference to the new instances, and they will get immediately discarded ("garbage collected", aka, deleted) after that line is processed.
This is how the above should actually be done:
mb = qtw.QMessageBox()
cb = qtw.QCheckBox()
mb.setCheckBox(cb)
cb.setText("Don't show this message again")
Now, there's a fundamental flaw in your code: question() is a static method (actually, for Python, it's more of a class method). Static and class methods are functions that don't act on an instance, but only on/for a class. Static methods of QMessageBox like question or warning create a new instance of QMessageBox using the provided arguments, so everything you've done before on the instance you created is completely ignored.
These methods are convenience functions that allow simple creation of message boxes without the need to write too much code. Since those methods only allow customization based on their arguments (which don't include adding a check box), you obviously cannot use them, and you must code what they do "under the hood" explicitly.
Here is how the final code should look:
# create the dialog with a parent, which will make it *modal*
mb = qtw.QMessageBox(self)
mb.setWindowTitle('Close application')
mb.setText('Do you really want to quit?')
# you can set the text on a checkbox directly from its constructor
cb = qtw.QCheckBox("Don't show this message again")
mb.setCheckBox(cb)
mb.setStandardButtons(mb.Yes | mb.No)
ret = mb.exec_()
# call some function that stores the checkbox state
self.storeCloseWarning(cb.isChecked())
if ret == mb.No:
return
self.close()
I'm writing an app using Flask and one of the things I want in it is the ability to upload a ZIP that conforms to a specific form; as such I have a small function that takes a FileStorage object from the form and first unzips it, checks the contents, and then tries to save. There's a problem, however - apparently unzipping it "breaks" the FileStorage object, as the following function:
def upload_modfile(modfile):
if not modfile.filename.endswith('.zip'):
raise ModError('Incorrect filename')
mod_path = join(get_mods_path(), secure_filename(modfile.filename))
if isfile(mod_path):
raise ModError('File ' + modfile.filename + ' already exists')
modzip = ZipFile(modfile)
base_filename = modfile.filename[:-4]
modzip_contents = modzip.namelist()
if join(base_filename, 'info.json') not in modzip_contents:
raise ModError('Could not validate file')
modfile.save(mod_path)
return True
saves modfile as a text file saying Archive: <filename>.zip. If I comment out the entire ZipFile bit (i.e. everything involving modzip), the file is saved just fine.
I'm pretty much brand new to Python and am a little confused as to what to do in this case, save for saving the file in /tmp. Should I somehow clone modfile by way of some stream? Is there a way of "rewinding" the stream pointer within FileStorage that I'm missing?
So, the title may seem vague, so I'm going to describe it in more detail here. I'm writing a space-themed text-based game as a project, and I've reached various problems. I'm trying to use multiple files to simply everything, and so, say I have these variables in file 1:
player_health = 100
o2 = 100
And that's fine and it works and all, but in the first file I have, I have an ever-growing check() function available (so the player can see game info), so I made another file to handle loops. In the second file, I have this, for example:
while True:
if o2 == 0:
time.sleep(2)
player_health = player_health -1
and for the player,
while True:
if player_health = 0
print(game_over)
Right now, o2 and player_health are set to 100 as variables. Game_over is a string I made, but that doesn't really matter currently. I defined o2 and player_health in file 1, say, and when I import file 2, they don't seem to work any more. Remember the While loops are handled in File 2. I could just put it all in one file, but then It would be harder for me to bugfix. The reason I'm doing this is so that I can handle the start and the loops and the actual story part separately, and add or remove loops as I see fit without having to sift through tons of code, like I would probably have to if it was all in a single file.
There's a lot of source code, So I'll just post snippets from file one and two. If you want to see all of the source code from both files, I could post it somehow, but there would be a lot.
File One Snippets:
(This is at the beginning of file one, which is named VortexA)
o2 = 100
nitrogen = 100
ship_store = []
player_inv = [] #These Lists and variables handle levels of life support and storage.
air = [o2, nitrogen]
ship_weapons = []
currency = 5
power = 0
He_3 = 0
ship_health = 0
player_health = 100
ship = False
(This is at the end of file one. Just adding it here)
print("Type start(game) to begin")
game = 1
def start(variable):
if game == 1: # This starts the game. Don't want everything in one file.
import vortexB
File 2 (vortexB) Snippets
I already posted some of the loops using variables above, but I'll post the errors I get here.
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
start(game)
File "C:\Users\Daniel\Desktop\Python Stuff\Python Game\vortexa.py", line 87, in start
import vortexb
File "C:\Users\Daniel\Desktop\Python Stuff\Python Game\vortexb.py", line 25, in <module>
print(player_health)
NameError: name 'player_health' is not defined
TL;DR:
Basically, I don't know if it's possible to import variables into another python file through the
import file
function. I'm trying to keep my game simple and easy to fix if something goes wrong by having separate files to handle loops and story.. If that's possible. If it's not, I'm going to have one hell of a messy file...
I'm just going to have the first file handle a tutorial-type thing, the second handle loops, and the third handle game-play elements.The way I want it set up is so that the variables are declared during a tutorial, and then the loops are in effect, and then I want the actual game to start. I feel like I'm missing something really simple, or what I'm trying to do is impossible. I strongly feel that it's something to do with o2 and nitrogen being stored in the air list, but that doesn't really explain player_health not being able to work. If it won't work at all, I'll see if there is another way to do it, like putting it all in one file.
Thanks in advance. Any and all help is appreciated.
Honestly, it sounds like you need a separation of concerns.
As for the title of this article goes, yes. You can import variables (lists, strings, objects, etc.) from specific files.
If you have a file constants.py:
class Player:
health = 100
power = 12
# etc
def __init__(self, name, power):
self.name = name
if power:
self.power = power
#property
def is_ded(self):
if self.health < 0:
return True
return False
And then inside of battle.py:
from constants import Player
me = Player('Kris', 500)
mic = Player('A microphone', 0)
def do_battle(player1, player2):
player1.health = player1.health - player2.power
player2.health = player2.health - player1.power
do_battle(me, mic)
mic.is_ded
# >>>True
me.is_ded
# >>>False
This is built into Python. Congratulations for picking the best language.
How can I get the Variables.save to save all variables, and not just the one specified by the user. I want to make sure that future runs of scons use exactly the same setup.
Sadly there is no way to do this using core SCons functions. The decision on whether to save a variable value or not is hard-wired into Save, and only values that are not the defaults can be saved.
However, you can save all variables by abusing the not-well-documented "converter" function. It ain't pretty, but does the job.
When you call Variables.Save(), it calls each variable's converter function and checks the result to see if it is the same as the default (input) value. If you return something that is not the input value when called from Save then all values are stored in the cache file. Elsewhere you need the converter to return the input value as-is, or it would use incorrect variable values.
def save_all(value, env=None):
import traceback
# if called in Save method, return non-default
for line in traceback.format_stack():
lines = line.splitlines()
if lines[0].endswith('Save'):
return value + 'save'
# return correct value otherwise
return value
import SCons
var = Variables("config.py", ARGUMENTS)
# AddVariables accepts tuples of:
# Variable key, description, default-value, validator, converter
var.AddVariables(
('CC', 'The C Compiler', 'cc', None, save_all),
('CFLAGS', 'Flags to pass to compiler', '-Wall', None, save_all))
env = Environment(tools=[], variables=var)
var.Save('config.py', env)
print 'CC', env['CC']
print 'CFLAGS', env['CFLAGS']
Here the function save_all is the hack. It uses the stack trace to check if it is called from within Save. If it is, then it returns a tampered value, otherwise it returns the input value unchanged. You can check the result of this example in the cache file "config.py".