I've made a custom operator for saving the current .blend file to a network drive. This yields about 20% performance boost compared to the default blender save function. First the .blend file is saved to the local temp directory and then moved over to the network drive.
Here is my code:
class toolbox_OP_SaveToNetwork(Operator):
bl_idname = 'toolbox.save_to_network'
bl_label = 'Save'
bl_description = "Save file locally and copy it to it's network path"
def execute(self, context):
if(bpy.data.is_saved == False):
return {"FINISHED"}
# return bpy.ops.toolbox.save_as_to_network("INVOKE_DEFAULT")
print("Save locally, copy to network drive...")
filename = bpy.path.basename(bpy.data.filepath)
tmp_filepath = os.path.join(tempfile.gettempdir(), filename)
report = bpy.ops.wm.save_as_mainfile(filepath=tmp_filepath, check_existing=False, copy=True)
if report == {"FINISHED"}:
# shutil seems to be slower than native os move
# shutil.move(tmp_filepath, bpy.data.filepath)
os.system('move %s %s' % (tmp_filepath, bpy.data.filepath))
return {"FINISHED"}
else:
return report
I would also like to implement the Save As functionality. This is helpful if I don't want to save by overriding my current file but rather incrementing it's version.
Now here is my problem:
Let's say I have test01.blend and want to save as test02.blend
If i use my script, then after saving the file the test01.blend file would still be opened in blender, because I have to use the copy=True argument in the bpy.ops.wm.save_as_mainfile operator. (This has to be used so blender does not open the .blend file which get saved in the local temp directory)
Is it somehow possible to change the filepath of the current opened .blend file via the python API without opening/loading a new file?
After the operation bpy.data.filepath should the point to path/to/file/test02.blend instead of path/to/file/test01.blend
Related
I am trying to create a simple GUI with streamlit and python for my aspect-based sentiment analysis project, the user should be able to upload a .txt file so that I can run the model on that file. I already created the widget for uploading a file. My question is:
The uploaded file should be added to a specific folder, how can I specify an exact location for the uploaded file to be saved?
uploaded_file = st.file_uploader('FILE UPLOAD')
(This is the code for the upload widget)
The file_uploader function does not save the file to disk, it writes to a BytesIO buffer.
The UploadedFile class is a subclass of BytesIO, and therefore it is “file-like”. This means you can pass them anywhere where a file is expected.
https://docs.streamlit.io/en/stable/api.html?highlight=file_uploader#streamlit.file_uploader
If you want to save the result as a file, use the standard Python file io capabilities:
with open(filename, "wb") as f:
f.write(buf.getbuffer())
To add to what #RandyZwitch said you can use this function to save to a directory of your choice (directory/folder "tempDir")
def save_uploaded_file(uploadedfile):
with open(os.path.join("tempDir",uploadedfile.name),"wb") as f:
f.write(uploadedfile.getbuffer())
return st.success("Saved file :{} in tempDir".format(uploadedfile.name))
And apply the function below your uploaded file like below
datafile = st.file_uploader("Upload CSV",type=['csv'])
if datafile is not None:
file_details = {"FileName":datafile.name,"FileType":datafile.type}
df = pd.read_csv(datafile)
st.dataframe(df)
# Apply Function here
save_uploaded_file(datafile)
You can define path like this:
from pathlib import Path
path = "C:/Projects/ex1/your_file"
file_path = Path(path)
uploaded_file = st.file_uploader(file_path)
I want the absolute path of the file selected as input file (from file browser in the form) using the python code below:
for attr, document in request.files.iteritems():
orig_filename = document.filename
print os.path.abspath(orig_filename)
mhash = get_hash_for_doc(orig_filename)
This prints the path of current working directory along(where the python script is executing) with the 'orig_filename' appended to it, which is the wrong path. I am using python 2.7, flask 0.12 under linux OS.
The requirement is to find the hash value of the file before uploading it to the server to check deduplication. So I need to use the algorithm by passing the file selected for hashing to another function as:
def get_hash_for_doc(orig_filename):
mhash = None
hash = sha1()#md5()
with open(mfile, "rb") as f:
for chunk in iter(lambda: f.read(128 * hash.block_size), b""):
hash.update(chunk)
mhash = hash.hexdigest()
return mhash
In this function I want to read file from absolute path of the orig_filename before uploading. Avoided all other code checks here.
First you need to create a temp file to simulate this required file then make your process on it
import tempfile, os
try:
fd, tmp = tempfile.mkstemp()
with os.fdopen(fd, 'w') as out:
out.write(file.read())
mhash = get_hash_for_doc(tmp)
finally:
os.unlink(tmp)
If you want to find a folder/file.ext, for an input file, simply use 'os.path.abspath' like:
savefile = os.path.abspath(Myinputfile)
when "Myinputfile" is a variable that contains the relative path and file name. For instance, derived from an argument define by the user.
But if you prefer to have absolute address of the folder, without file name try this:
saveloc = os.path.dirname(os.path.realpath(Myinputfile))
You can use pathlib to find the absolute path of the selected file.
Flask-uploads has something called UploadSet which is described as a "single collection of files". I can use this upload set to save my file to a predefined location. I've defined my setup:
app = Flask(__name__)
app.config['UPLOADS_DEFAULT_DEST'] = os.path.realpath('.') + '/uploads'
app.config['UPLOADED_PHOTOS_ALLOW'] = set(['png', 'jpg', 'jpeg'])
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
# setup flask-uploads
photos = UploadSet('photos')
configure_uploads(app, photos)
#app.route('/doit', method=["POST"])
def doit():
myfile = request.files['file']
photos.save(myfile, 'subfolder_test', 'filename_test')
return ''' blah '''
This should save to ./uploads/photos/subfolder_test/filename_test.png
My test image is: 2.6MB and is a png file. When I upload this file, I get the error:
...
File "/home/btw/flask/app.py", line 57, in doit
photos.save(myfile, 'subfolder_test', 'filename_test')
File "/usr/local/lib/python2.7/dist-packages/flaskext/uploads.py", line 388, in save
raise UploadNotAllowed()
UploadNotAllowed
However it doesn't say exactly what is not allowed. I have also tried removing all constraints, but the app still throws this error. Why?
EDIT:
Okay, so I figured out that it's not actually the constraints that is causing the problem. It is the subfolder and/or the filename that is causing the problem:
# This works
# saves to: ./uploads/photos/filename_test.png
photos.save(myfile)
But I want to save to my custom location ./uploads/photos/<custom_subdir>/<custom_filename>. What is the correct way of doing this?
You need to give your filename_test the extension as well
photos.save(myfile, 'subfolder_test', 'filename_test.png')
The UploadSet checks the extension on the new file name and will throw the exception if the new extension is not allowed.
Since you are not giving the new file an extension, it does not recognize it.
You can add a dot to file's name, then the file's extension will be appended.
photos.save(myfile, 'subfolder_test', 'filename_test' + '.')
save(storage, folder=None, name=None)
Parameters:
storage – The uploaded file to save.
folder – The subfolder within the upload set to save to.
name – The name to save the file as. If it ends with a dot, the file’s extension will be appended to the end.
So I have a XLS file that is being accessed via the xlutils library. When my program is finished doing its process, its supposed to delete the original file and rename the temporary file to the original file. The data in the excel file is being input a website and data from the website is being extracted and then written to the excel sheet. All this is fine, however, when its done its having an issue renaming the temp file.
The temp file is simply a copy made via the following function:
def rename(self, fpath):
tempf=os.path.splitext(fpath)[0]
tempf=tempf + "-output" + ".xls"
shutil.copyfile(fpath,tempf)
return tempf
I have created a function which is called when the for loop for inputting data and extracting is finished:
def allDone(self, event):
dlg = wx.MessageBox("All done!", "Ask Alfred", wx.OK | wx.ICON_INFORMATION)
os.unlink(self.fpath)
os.rename(self.temp, self.fpath)
Using Process Explorer, it shows that the temp file is still open in python.exe. I don't know how to close the file and free memory since it is being opened by using:
rbook=open_workbook(file)
sheet = rbook.sheet_by_index(0)
where file will simply be replaced with whatever self.temp is.
When a GO button is pushed the following happens:
def onGo(self, event):
fpath=self.pathBox
fpath=fpath.GetValue()
self.fpath=fpath
temp=myClass.rename(fpath)
self.temp=temp
openFile(temp)
def rename(self, fpath):
tempf=os.path.splitext(fpath)[0]
tempf=tempf + ".alf"
shutil.copyfile(fpath,tempf)
return tempf
So the name of the file which is in a SearchCtrl called "pathBox" is obtained and a temp copy is made and then renamed.
The following code is successfully uploading an image file using the Bottle framework.
upload = bottle.request.files.get("filPhoto01")
if upload is not None:
name, ext = os.path.splitext(upload.filename)
if ext not in ('.png','.jpg','.jpeg'):
return "File extension not allowed."
save_path = "/tmp/abc".format(category=category)
if not os.path.exists(save_path):
os.makedirs(save_path)
file_path = "{path}/{file}".format(path=save_path, file=upload.filename)
with open(file_path, 'w') as open_file:
open_file.write(upload.file.read())
However, when I try to open this file manually after upload, I can't open the file. I can see the icon of the uploaded file with the correct size (implying the whole image was uploaded), but I cannot view it in any application like MS paint, etc.
I also tried referencing the file in my web application, but it does not render there either. What could possibly be wrong?
Just a guess, but since it sounds like you're on Windows, you'll want to write the file in binary mode:
with open(file_path, 'wb') as open_file:
(Also, you didn't mention your Python version, but FYI in Python 3 you'd need to use binary mode even on Linux.)