Community
Fusion API and Scripts
Got a new add-in to share? Need something specialized to be scripted? Ask questions or share what you’ve discovered with the community.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Runtime error trying to determine whether a data file exists in a project folder

5 REPLIES 5
SOLVED
Reply
Message 1 of 6
bloudraak
291 Views, 5 Replies

Runtime error trying to determine whether a data file exists in a project folder

I'm trying to see whether a document already exists within a subfolder of a project. The code to check looks as follows:

def file_exists(parent: adsk.core.DataFolder, name: str):
    files = parent.dataFiles.asArray()
    for file in files:
        if file.name == name:
            return True
    return False

It's then used in a loop as follows

def run(context):
    try:
        ui = None
        app = adsk.core.Application.get()
        ui = app.userInterface
        project: adsk.core.DataProject = app.data.activeProject
        for d in items:
            name = d.name
            folder = project.rootFolder.dataFolders.itemByName("Items")
            if file_exists(folder, name):
                continue
            doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
            # do stuff
            doc.saveAs(name, folder, '', '')
            doc.close(False)

Say the items were A, B, C, D, and E. The first time it runs, it will succeed for A, and A is created, but throw an exception for B. When you run it again, the function succeeds for A and B, but then fails for C, and so on and so forth. The error being produced is this:

wernersLNPQD_0-1642435486405.png

I have tried other combinations suggested in the forum, namely by looping through the data files using an index, enumerating through them. But they all fail with an error similar to this.

 

How does one reliably check if a file exists in a folder of a project?

Software Engineer
https://wernerstrydom.com
5 REPLIES 5
Message 2 of 6
kandennti
in reply to: bloudraak

Hi @bloudraak .

 

I wasn't sure what was in the "items" variable, but I interpreted it as multiple open documents and tried it, and sure enough, I got an error.

 

I think the reason is that the DataFolder is accessed many times in a short period of time, or while saving.

 

In order to minimize the number of accesses to the DataFolder, it may be possible to create a list of file names first and compare them with the list to avoid the error.

# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core


def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface
        project: adsk.core.DataProject = app.data.activeProject

        # Open documents
        items = app.documents

        # get file name list
        folder: adsk.core.DataFolder = project.rootFolder.dataFolders.itemByName(
            "Items")
        fileNames = [df.name for df in folder.dataFiles.asArray()]

        for d in items:
            name = d.name
            if name in fileNames:
                app.log(f'{name} : true')
                continue

            app.log(f'{name} : false')
            doc = app.documents.add(
                adsk.core.DocumentTypes.FusionDesignDocumentType)
            # do stuff
            doc.saveAs(name, folder, '', '')
            doc.close(False)

            fileNames.append(name)

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Message 3 of 6
bloudraak
in reply to: bloudraak

Items were just a phyton array of objects. 

 

class ItemDefinition:
    def __init__(self, name, depth, width):
        self.name = name
        self.width = width
        self.depth = depth


items = [
    ItemDefinition('Bla', 6.948, 4.267),
]
Software Engineer
https://wernerstrydom.com
Message 4 of 6
j.han97
in reply to: bloudraak

Here are my speculations:

 

Based on the facts:

1. API is able to check current items in the folder

2. API failed to check current items after creating (and saving) something in the folder

 

I guess that saving new items refreshes/updates the state (version ID) of the folder, therefore trying to access the folder after creating new items always fails.

 

You can try to get the list of items in the folder in the beginning for once only as suggested by @kandennti and see if the problem still exists.

Message 5 of 6
BrianEkins
in reply to: bloudraak

There is some information and additional capabilities discussed in the "What's New" for the January release.

 

Below is a modified version of your program that uses the new DataFile.isComplete property.  However, when I was first testing I mistakenly was checking the Document.isSaved property which was immediately returning before the document was fully saved and everything was still working as expected.

 

import adsk.core, adsk.fusion, adsk.cam, traceback
import time

class ItemDefinition:
    def __init__(self, name, depth, width):
        self.name = name
        self.width = width
        self.depth = depth

def file_exists(parent: adsk.core.DataFolder, name: str):
    files = parent.dataFiles.asArray()
    for file in files:
        if file.name == name:
            return True
    return False

def run(context):
    try:
        items = [ItemDefinition('One', 6.948, 4.267),
                 ItemDefinition('Two', 6.948, 4.267),
                 ItemDefinition('Three', 6.948, 4.267),
                 ItemDefinition('Three', 6.948, 4.267)]
        ui = None
        app = adsk.core.Application.get()
        ui = app.userInterface
        project: adsk.core.DataProject = app.data.activeProject
        for d in items:
            name = d.name
            folder = project.rootFolder.dataFolders.itemByName("Items")
            if file_exists(folder, name):
                app.log(f'{name} already exists.')
                continue

            doc: adsk.core.Document = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
            des: adsk.fusion.Design = doc.products.itemByProductType('DesignProductType')
            root = des.rootComponent
            sk: adsk.fusion.Sketch = root.sketches.add(root.xYConstructionPlane)
            sk.sketchCurves.sketchLines.addCenterPointRectangle(adsk.core.Point3D.create(0,0,0),
                                                                adsk.core.Point3D.create(5,3,0))
            prof = sk.profiles.item(0)
            root.features.extrudeFeatures.addSimple(prof, adsk.core.ValueInput.createByReal(4), adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
            doc.saveAs(name, folder, '', '')

            # Spin until the save is complete, up to 10 seconds and then abort.
            startTime = time.time()
            endTime = startTime + 10
            while not doc.dataFile.isComplete and time.time() < endTime:
                app.log('Waiting for save to finish.')
                time.sleep(0.5)
                adsk.doEvents()

            doc.close(False)
            app.log(f'Successfully created {name}.')
    except:
        app.log('Failed.')

 

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
Message 6 of 6
bloudraak
in reply to: bloudraak

That solved a few "race conditions" I encountered creating numerous documents. 

 

Thanks!

Software Engineer
https://wernerstrydom.com

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report