Can I prevent FreeCad from caching Python files? - python

I am trying to learn Python scripting for FreeCad.
In the folder "C:/p/Freecad/0.18/ZillmannTest" I have
2 files:
Macro1.py and
FCadHelper.py
The content of Macro1.py is as follows:
############
import sys
sys.path.append("C:/p/Freecad/0.18/ZillmannTest")
from FCadHelper import *
helper = FCadHelper()
helper.startDocument('TestKopf')
helper.addBody('TestKopfBody')
helper.addSketch('TestSketch')
####################
I can start Macro1.py from FreeCad Macro menu
But when I have an error in FCadHelper.py and correct it,
FreeCad does not load the changed file FCadHelper.py,
it keeps using the old (chached ?) version of the file.
To use the changed file I have to terminate FreeCad and
start it again. Which is annoying.
Is there a way to stop FreeCad from caching this file?
As I plan to create a Class library of similar files,
the problem will then be even greater than now.
Kind regards

You can try importlib.reload:
https://docs.python.org/3/library/importlib.html#importlib.reload
It is a little tricky sometimes, but it will work in your case.

Related

How to make a file with python using nikkiepy

I've been stuck on C++ for a bit, so I decided to continue my python classes (In which I'm currently working with the Nikkiepy library) and I'm trying to figure out how to make a file. This is my current code:
import nikkiepy.files as npyf
npyf.mkfile("coakey", "./data", ".cde")
for some reason it keeps asking for a folder
You're using "Coakey" as the folder, you should instead do
import nikkiepy.files as npyf
npyf.mkfile(path="./", name="coakey", extension="cde")
Also, leave the "." out of the extension, because that gets added automatically

How to debug a PyInstaller .spec file?

Suppose I have a minimal PyInstaller spec file, e.g. the hello_world.spec that is created when I run pyinstaller hello_world.py (also see docs). This spec file has python code but no import statements.
Now suppose I customize this file, e.g. using the Tree and TOC classes, but something is going wrong and I need to find out what.
I am aware of the PyInstaller --log-level options and warn*.txt files, but I would prefer to place some break-points in my IDE and debug the spec file (or maybe just play around with the Tree class in the console). However, debugging does not work out-of-the-box because there are no import statements in the spec file. I can add those, as below, for example:
from PyInstaller.building.build_main import Analysis, PYZ, EXE, COLLECT
from PyInstaller.building.datastruct import TOC, Tree
But then it turns out some configuration info is required, as I keep running into KeyErrors related to CONF. I tried adding those key/value-pairs manually, based on a list of globals from the docs, which appears to work, up to a point, but I cannot help thinking I'm doing something wrong...
import PyInstaller.config
PyInstaller.config.CONF['specnm'] = 'hello_world'
... etc. ...
Could someone tell me what is the right way to do this? Should I just stick with the pyinstaller --log-level approach?
A couple of years later, still no answer, so here's one alternative I came up with:
One approach is to use unittest.mock.Mock to mock the PyInstaller classes that are not relevant for the problem at hand.
For example, my spec file has some custom code that generates some of the values passed into the Analysis class. In order to debug that code, I just mock out all the PyInstaller classes and run the spec file, using runpy.run_path from the standard library, as follows:
from runpy import run_path
from unittest.mock import Mock
mocks = dict(Analysis=Mock(), EXE=Mock(), PYZ=Mock(), COLLECT=Mock())
run_path(path_name="path/to/my.spec", init_globals=mocks)
This is also very useful to extract the values of arguments defined in the spec file. For example, we can extract the name value passed into EXE() as follows:
exe_name = mocks["EXE"].call_args.kwargs["name"]
Found this unresolved thread, I found that putting an old style Python breakpoint in the spec file works with Pyinstaller 4.8:
...
import pdb; pdb.set_trace()
...

Making a directory for a file

I was making a exercise generator algorithm for my friend, but I stumbled across a problem. It is a python program, and I wanted to generate a folder in a directory that was above the program's location (like, the python file is in 'C:\Documents\foo' and the folder should be created in 'C:\Documents') so that it could then store the file the program created. Is there a way to do this or should I try something else?
Use the path argument of the os.mkdir() function.
Getting the current script directory is not a built-in feature, but there are multiple hacks suggested here.
Once you get the current script directory, you can build a path based off of that.
Not super familiar with Python in a Windows environment, but this should be easily do-able. Here is a similar question that might be worth looking at: How to check if a directory exists and create it if necessary?
Looks like the pathlib module might do what you are looking for.
from pathlib import Path
path = Path("/my/directory/filename.txt")
try:
if not path.parent.exists():
path.parent.mkdir(parents=True)
except OSError:
# handle error; you can also catch specific errors like
# FileExistsError and so on.
Appears to work on Win 7 with Python 2.7.8 as described:
import os.path
createDir = '\\'.join((os.path.abspath(os.path.join(os.getcwd(), os.pardir)), 'Foo'))
if not os.path.exists(createDir):
os.makedirs(createDir)

Trouble with modules while embedding python in C++

I'm making a .dll for an .exe program and embedding python in it. It worked fine with this simple .py program
from time import *
##import OptimRestriction
def test_callsign(b):
...(simple script)
return
What I did was copy the .py program, the Dll and Lib folders into the xxx.exe folder, like is said here.
But as soon as I uncomment the import of OptimRestriction the debug crashes. First it starts loading symbols when the call to the thread that initializes and deals with Python is called: _ctypes.pyd,_sockets.pyd,sst_pyd,harshlib.pyd,unicodedata.pyd,tkinter.pyd, all modules that the OptimRestriction does not use.
The error given after the debug crashes is:
Unhandled exception at 0x1E0AA0C5 (python27.dll) in xxx.exe: 0xC0000005: Access violation reading location 0x00000004.
And it breaks on the _callthreadstart function.
OptimRestriction is a long program that imports a lot of modules (that are also in the .exe folder). Here's the list of its imports:
from GrafFunc import *
from LogFunc import *
from DinamicaFunc import *
from Dinamica2 import *
from CDR import *
...
import sys
import cProfile"
What it seems to me is that the thread takes too long to start because the debug starts loading those files for a long time, and so it gives an error. Am I correct? And if so, why is it loading those files if OptimRestrictionand its impots don't use them?
Edit:New information. It crashes saying Can't import module on this line:
pModule = PyImport_Import(pName);
After long hours of reducing the problem to some lines of code, i just found out that the problem was in the lines where some of the modules opened .txt files to read.
I thought that having the .txt files in the same folder of the .py programs was the correct thing to do, but it seems that I needed to copy them to the folder of my c++ plugin (I think that's because while I'm debugging, the system path is changed for my plug-in folder since the writing and reading of pyhton is done to/from there)
Problem solved!

How to automatically execute python script when Maya first loaded

I am trying to figure out how to use Python in Maya. I wanted to create a shelf in Maya and when I click that shelf, it will execute a file containing python code.
First thing, I figured out that we can't simply source python script. I followed this tutorial, so now I have a function psource(). In my shelf, I can just call psource("myPythonScript")
My problem is I have to somehow register psource() when Maya first loaded.
Any idea how to do this?
I suggest that you import the Python module with your button before calling the function. Assuming your script is in maya/scripts/tep.py, your button would do the following:
import tep
tep.psource()
If you wanted to modify the script and keep running the fresh version every time you hit the button, do this:
import tep
reload(tep)
tep.psource()
And if you want your module to load on Maya startup, create a file called userSetup.py in your maya/scripts directory and have it do this:
import tep
Then, your button can simply just:
tep.psource()
Or...
reload(tep)
tep.psource()
As part of the Maya startup sequence, it'll execute a file called userSetup.py for you. Within that file you can stick in standard python code to set up your environment, etc.
docs: http://download.autodesk.com/global/docs/maya2013/en_us/index.html?url=files/Python_Python_in_Maya.htm,topicNumber=d30e725143
That's the 2013 docco, but it's valid in 2011 and 2012 too. I expect it to be correct going back further as well, but I'm not running anything older here
For an example btw, my userSetup.py file looks like this:
import sys
# import a separate pyscript dir - we keep the standard scriptdir for MEL
sys.path.append(r'C:/Users/tanantish/Documents/maya/2012-x64/pyscripts')
# odds on i'm going to want PyMEL loaded by default
# and we are going to try distinguish it from the old maya.cmds
# since the two since they're similar, but not the same.
# from pymel.core import *
import pymel.core as pm
# and we might as well get maya.cmds in for testing..
import maya.cmds as mc
# import local toolpack
import tantools
(edited to caps out userSetup.py as per #jdi's comment)
Which version of Maya are you running? If later than 8.5, Maya has python built in. Any python scripts you put in your local Maya script directory gets automatically sourced. You can inside the script editor source and run python scripts.
To automatically run:
Create a userSetup.mel file in myDocs\maya\mayaVersion\scripts
Inside the userSetup, use this syntax to import and run scripts:
python("from package import module");
python("module.method(\"passedVar1\", \"passedVar2\")");
Hope that helps
P.S Same syntax applies for shelf buttons. Just have to make sure that you have your python path set for Maya so that your code can be found. The local script directory is already included.....
I like to use
exec(open('c:\whatever\whatever\scriptname.py'))
See if that works for you! :)

Categories

Resources