Save Outfile with Python Loop in SPSS - python

Ok so I've been playing with python and spss to achieve almost what I want. I am able to open the file and make the changes, however I am having trouble saving the files (and those changes). What I have (using only one school in the schoollist):
begin program.
import spss, spssaux
import os
schoollist = ['brow']
for x in schoollist:
school = 'brow'
school2 = school + '06.sav'
filename = os.path.join("Y:\...\Data", school2) #In this instance, Y:\...\Data\brow06.sav
spssaux.OpenDataFile(filename)
#--This block are the changes and not particularly relevant to the question--#
cur=spss.Cursor(accessType='w')
cur.SetVarNameAndType(['name'],[8])
cur.CommitDictionary()
for i in range(cur.GetCaseCount()):
cur.fetchone()
cur.SetValueChar('name', school)
cur.CommitCase()
cur.close()
#-- What am I doing wrong here? --#
spss.Submit("save outfile = filename".)
end program.
Any suggestions on how to get the save outfile to work with the loop? Thanks. Cheers

In your save call, you are not resolving filename to its actual value. It should be something like this:
spss.Submit("""save outfile="%s".""" % filename)

I'm unfamiliar with spssaux.OpenDataFile and can't find any documentation on it (besides references to working with SPSS data files in unicode mode). But what I am going to guess is the problem is that it grabs the SPSS data file for use in the Python program block, but it isn't actually opened to further submit commands.
Here I make a test case that instead of using spssaux.OpenDataFile to grab the file, does it all with SPSS commands and just inserts the necessary parts via python. So first lets create some fake data to work with.
*Prepping the example data files.
FILE HANDLE save /NAME = 'C:\Users\andrew.wheeler\Desktop\TestPython'.
DATA LIST FREE / A .
BEGIN DATA
1
2
3
END DATA.
SAVE OUTFILE = "save\Test1.sav".
SAVE OUTFILE = "save\Test2.sav".
SAVE OUTFILE = "save\Test3.sav".
DATASET CLOSE ALL.
Now here is a paired down version of what your code is doing. I have the LIST ALL. command inserted in so you can check the output that it is adding the variable of interest to the file.
*Sequential opening the data files and appending data name.
BEGIN PROGRAM.
import spss
import os
schoollist = ['1','2','3']
for x in schoollist:
school2 = 'Test' + x + '.sav'
filename = os.path.join("C:\\Users\\andrew.wheeler\\Desktop\\TestPython", school2)
#opens the SPSS file and makes a new variable for the school name
spss.Submit("""
GET FILE = "%s".
STRING Name (A20).
COMPUTE Name = "%s".
LIST ALL.
SAVE OUTFILE = "%s".
""" %(filename, x,filename))
END PROGRAM.

Related

How do you make sure a txt file with a dictionary in it can't be edited?

So I am trying to add save files to my text-adventure game that can't be edited by the user. This is so that they can't cheat by editing the dictionary inside of it. So far all I've done is a few algorithms that can be easily bypassed if you connected the dots. Basically it's this.
import sys,os,ast
dictionary = {...}
save_dictionary = {...}
def save():
filehandler = open("dictionary.txt", "a")
data = str(dictionary)
filehandler.write(data)
filehandler.close()
def savecode():
savecode = dictionary.values()
total = sum(savecode)
save_dictionary['savecodes'] = round(math formulas)
filehandler = open("save_dictionary.txt", "a")
data = str(save_dictionary)
filehandler.write(data)
filehandler.close()
def load():
with open('dictionary.txt') as f:
data = f.read()
save = ast.literal_eval(data)
f.close()
But the problem I'm facing is that it is easily by-passible if you just add an amount and equally subtract an amount, which would make the sum the same, making everything work the same. I did make it so that anytime the game itself detects any changes it immediately deletes all save files and makes you start over.
So is the solution making the files unable to be accessed at all? Or is it that the python file will detect the time it was created? I have no idea. It could be another option.
You can't hide files from the super user. They bought their computer and they reserve the right to read and edit whatever files they please. And no program will ever have higher permissions than the administrator.
Your best bet is to encrypt the data inside the file. So that if the user tries to edit, the program won't function properly.
A question that might be more relevant:
https://gamedev.stackexchange.com/questions/48629/how-do-i-prevent-memory-modification-cheats

Using output .csv file from one python script in another

I am currently using two different types of python scripts. One extracts data and saves it as a CSV file, and the other characterizes data. Both work perfectly separately, but I am trying to find a way to characterize the data from the outputted CSV file without having to run them separately. Importing script1 into script2 is easy, but reading the CSV file from script1 is what I can't figure out. I am going to provide the output of script1 and where I am trying to insert it in script2:
# create file or append to file
filename = '%s.csv' % gps
if os.path.exists(filename):
append_write = 'a' # append if already exists
else:
append_write = 'w' # make a new file if not
# save file
with open('!/usr/bin/env python/%s.csv' % gps, mode=append_write) as features_file:
features_writer = csv.writer(features_file, delimiter=' ', quotechar='"', quoting=csv.QUOTE_MINIMAL)
(!/usr/bin/env python has replaced the directory I am actually saving this CSV file in due to privacy reasons.)
I am trying to then place the file from this output into the following command:
x_new = pd.read_csv('filename %s.csv gps' , names = attributes)
I have tried a variety of ways to input the script1 output into this command, but can't find the correct way to do this. Please help me out. If any further information is needed please let me know.
This line is definitely wrong:
x_new = pd.read_csv('filename %s.csv gps' , names = attributes)
probably you mean:
x_new = pd.read_csv(filename , names = attributes)
Or
x_new = pd.read_csv('%s.csv' % gps , names = attributes)
but I don't think the filename part should be there either.
But don't write it to a file. You can just keep manipulating the data. And if you want to save the file anyway, you don't have to read the file, you can still just keep manipulating the array/frame you have.
also open(filename,"w") is all you need, if the file doesn't exist, it will be created.
You should try using formatted strings and putting variable directly into your file filepath (this assumes you're using Python 3+) :
x_new = pd.read_csv(f'{gps}.csv')

How to store a txt file in your program and reference it

Let me preface by saying I am very new to programming. I'm creating a fun program that I can use to start my day at work. One of the things I want it to do is display a random compliment. I made a text file that has multiple lines in it. How do I store that text file then open it?
I've opened text files before that were on my desktop but I want this one to be embedded in the code so when I compile the program I can take it to any computer.
I've googled a ton of different key words and keep finding the basics of opening and reading txt files but that's not exactly what I need.
Perhaps start with defining a default path to your file; this makes it easier to change the path when moving to another computer. Next, define a function in your program to read and return the contents of the file:
FILE_PATH = "my/path/to/file/"
def read_file(file_name):
with open(FILE_PATH + file_name) as f:
return f.read()
With that in place, you can use this function to read, modify, or display the file contents, for example to edit something from your file:
def edit_comments():
text = read_file("daily_comments.txt")
text = text.replace("foo", "foo2")
return text
There are obviously many ways to approach this task, this is just a simple example to get you started.

How Do I Change the Data Stored in a Text File in Python?

I am trying to create a basic mathematical quiz and need to be able to store the name of the user next to their score. To ensure that I could edit the data dynamically regardless of the length of the user's name or the number of digits in their score, I decided to split up the name and score with a comma and use the split function. I'm new to file handling in python so don't know if I am using the wrong mode ("r+") but when I complete the quiz, my score is not recorded at all, nothing is added to the file. Here is my code:
for line in class_results.read():
if student_full_name in line:
student = line.split(",")
student[1] = correct
line.replace(line, "{},{}".format(student_full_name, student[1]))
else:
class_results.write("{},{}".format(student_full_name, correct))
Please let me know how I can get this system to work. Thank you in advance.
Yes r+ opens the file for both reading and writing and to summarize:
r when the file will only be read
w for only writing (an existing file with the same name will be erased)
a opens the file for appending; any data written to the file is automatically added to the end.
I will recommend instead of comma separation to benifit from json or yaml syntax, it fits better in this case.
scores.json:
{
"student1": 12,
"student2": 798
}
The solution:
import json
with open(filename, "r+") as data:
scores_dict = json.loads(data.read())
scores_dict[student_full_name] = correct # if already exist it will be updated otherwise it will be added
data.seek(0)
data.write(json.dumps(scores_dict))
data.truncate()
scores.yml will looks as follow:
student1: 45
student2: 7986
Solution:
import yaml
with open(filename, "r+") as data:
scores_dict = yaml.loads(data.read())
scores_dict[student_full_name] = correct # if already exist it will be updated otherwise it will be added
data.seek(0)
data.write(yaml.dump(scores_dict, default_flow_style=False))
data.truncate()
to instal yaml python package: pip install pyyaml
Modifying a file in place is generally a poor way to do this. It risks errors causing the resulting file to be half new data, half old, with the split point being corrupted. The usual pattern is to write to a new file, then atomically replace the old file with the new file, so either you have the entire original old file and a partial new file, or the new file, not a mish-mash of both.
Given your example code, here is how you would fix it up to do that:
import csv
import os
from tempfile import NamedTemporaryFile
origfile = '...'
origdir = os.path.dirname(origfile)
# Open original file for read, and tempfile in same directory for write
with open(origfile, newline='') as inf, NamedTemporaryFile('w', dir=origdir, newline='') as outf:
old_results = csv.reader(inf)
new_results = csv.writer(outf)
for name, oldscore in old_results:
if name == student_full_name:
# Found our student, replace their score
new_results.writerow((name, correct))
# The write out the rest of the lines unchanged
new_results.writerows(old_results)
# and we're done
break
else:
new_results.writerow((name, oldscore))
else:
# else block on for loop executes if loop ran without break-ing
new_results.writerow((student_full_name, correct))
# If we got here, no exceptions, so let's keep the new data to replace the old
outf.delete = False
# Atomically replaces the original file with the temp file with updated data
os.replace(outf.name, origfile)

RegEx Python Find and Print to a new document

Sorry if this is a dumb lump of questions, but I had a couple things I was hoping to inquire about. Basically, what I am trying to do is take a file that is being sent where a bunch of data is getting clumped all together that is supposed to be on separate lines, sort through it, and print each statement on its own line. The thing I don't know is how to create a new document for everything to be dumped into, nor do I know how to print into that document where each thing is on its new line.
I've decided to try and tackle this task while using Regular Expressions and Python. I want my code to look for any of four specific strings (MTH|, SCN|, ENG|, or HST|) and copy everything after it UNTIL it runs into one of those four strings again. At that point I need it to stop, record everything it copied, and then start copying the new string. I need to make it read past new lines and ignore them, which I hope to accomplish with
re.DOTALL
Basically, I want my code to take something like this:
MTH|stuffstuffstuffSCN|stuffstuffstuffENG|stuffstuffstuffHST|stuffstu
ffstuffSCN|stuffstuffstuffENG|stuffstuffstuffHST|stuffstuffstuffMTH|s
tuffstuffstuffSCN|stuffstuffstuffENG|stuffstuffstuff
And turn into something nice and readable like this:
MTH|stuffstuffstuff
SCN|stuffstuffstuff
ENG|stuffstuffstuff
HST|stuffstuffstuff
SCN|stuffstuffstuff
ENG|stuffstuffstuff
HST|stuffstuffstuff
MTH|stuffstuffstuff
SCN|stuffstuffstuff
ENG|stuffstuffstuff
While also creating a new document and pasting it all in that .txt file. My code looks like this so far:
import re
re.DOTALL
from __future__ import print_function
NDoc = raw_input("Enter name of to-be-made document")
log = open("C:\Users\XYZ\Desktop\Python\NDoc.txt", "w")
#Need help with this^ How do I make new file instead of opening a file?
nl = list()
file = raw_input("Enter a file to be sorted")
xfile = open(file)
for line in xfile:
l=line.strip()
n=re.findall('^([MTH|SCN|ENG|HST][|].)$[MTH|SCN|ENG|HST][|]',l)
#Edited out some x's here that I left in, sorry
if len(n) > 0:
nl.append(n)
for item in nl:
print(item, file = log)
In the starting file, stuffstuffstuff can be number, letters, and various symbols (including | ), but no where except where they are supposed to be will MTH| SCN| ENG| HST| occur, so I want to look specifically for those 4 strings as my starts and ends.
Aside from being able to create a new document and paste into it on separate lines for each item in list, will the above code accomplish what I am trying to do? Can I scan .txt files and excel files? I don't have a file to test it on till Friday but I am supposed to have it mostly done by then.
Oh, also, to do things like:
import.re
re.DOTALL
from __future__ import print_function
do I have to set anything external? Are these addons or things I need to import or are these all just built into python?
This regex will take your string and put newlines in between each string you wanted to separate:
re.sub("(\B)(?=((MTH|SCN|ENG|HST)[|]))","\n\n",line)
Here is the code I was testing with:
from __future__ import print_function
import re
#NDoc = raw_input("Enter name of to-be-made document")
#log = open("C:\Users\XYZ\Desktop\Python\NDoc.txt", "w")
#Need help with this^ How do I make new file instead of opening a file?
#nl = list()
#file = raw_input("Enter a file to be sorted")
xfile = open("file2")
for line in xfile:
l=line.strip()
n=re.sub("(\B)(?=((MTH|SCN|ENG|HST)[|]))","\n\n",line)
#Edited out some x's here that I left in, sorry
if len(n) > 0:
nl=n.split("\n")
for item in nl:
print(item)
I've tested this version with input data that has no newlines. I also have a version that works with newlines. If this doesn't work, let me know and I'll post that version.
The main environmental changes I made are that I'm reading from a file named "file2" in the same directory as the python script and I'm just writing the output to the screen.
This version assumes that there are newlines in your data and just reads the whole file in:
from __future__ import print_function
import re
#NDoc = raw_input("Enter name of to-be-made document")
#log = open("C:\Users\XYZ\Desktop\Python\NDoc.txt", "w")
#Need help with this^ How do I make new file instead of opening a file?
#nl = list()
#file = raw_input("Enter a file to be sorted")
xfile = open("file")
line = xfile.read()
l=line.strip()
l=re.sub("\n","",l)
n=re.sub("(\B)(?=((MTH|SCN|ENG|HST)[|]))","\n\n",l)
print(n)

Categories