I've the following AutoLISP code
(defun graph ( pts sls tls ) ( (lambda ( l ) (foreach x l (text (cdr x) (itoa (car x)) 0.0 1)) (mapcar '(lambda ( a b / p q r ) (setq p (cdr (assoc a l)) q (cdr (assoc b l)) r (angle p q) ) (entmake (list '(0 . "LINE") (cons 10 p) (cons 11 q) '(62 . 8))) (text (mapcar '(lambda ( x y ) (/ (+ x y) 2.0)) p q) (rtos (distance p q) 2) (if (and (< (* pi 0.5) r) (<= r (* pi 1.5))) (+ r pi) r) 2 ) ) sls tls ) ) (mapcar 'cons (vl-sort (append sls tls) '<) pts) ) ) (defun text ( p s a c ) (entmake (list '(0 . "TEXT") (cons 10 p) (cons 11 p) (cons 50 a) (cons 01 s) (cons 62 c) '(40 . 2) '(72 . 1) '(73 . 2) ) ) )
and the input is
(graph '((75 25) (115 45) (90 60) (10 5) (45 0) (45 55) (0 25)) '(1 1 1 1 2 2 3 4 4 5 6) '(2 3 4 5 3 6 6 5 7 7 7) )
The 2D geometry created from the above is exported as a dxf file from AutoCAD.
The actual input is generated in Python
pts = [(75, 25), (115, 45), (90, 60), (10, 5), (45, 0), (45, 55), (0, 25)]sls = [1 1 1 1 2 2 3 4 4 5 6] tls = [2 3 4 5 3 6 6 5 7 7 7]
I would like to know how to use the python data types as input and directly interface with AutoCAD from Python, save the AutoCAD output as a dxf file.
Solved! Go to Solution.
Did you google ? I dont use Python. But found examples.
#Get running instance of the AutoCAD applicationacad = comtypes.client.GetActiveObject("AutoCAD.Application")
Yes, I did.
I found this library https://pyautocad.readthedocs.io/en/latest/usage.html
But I don't understand how to run the above code after doing pip install pyautocad
You have to rewrite your script how is stated in your link.
Miljenko Hatlak
Thank you.
After installing pyautocad I did
from pyautocad import Autocad, APoint
Now I am not sure how to evaluate these AutoCAD expressions in Python.
For instance, the inputs are Python tuples
(graph '((75 25) (115 45) (90 60) (10 5) (45 0) (45 55) (0 25)) '(1 1 1 1 2 2 3 4 4 5 6) '(2 3 4 5 3 6 6 5 7 7 7) )
. Should I convert each tuple to AutoCAD point using
p = APoint(x, y)
And I am not sure how to proceed from here after generating the input data as autocad points. It's not clear to me how the commands in function
defun graph ( pts sls tls )
have to be modified. Could you please elaborate a bit on this?
Sorry I cant help you with this. Whole function has to be written in pyautocad.
Miljenko Hatlak
https://stackoverflow.com/questions/48794935/batch-run-autolisp-with-python
Miljenko Hatlak
Thank you, the python code is helpful. I'd like to ask for a few clarifications
acad = GetActiveObject("AutoCAD.Application.20")
I would like to know if the AutoCAD application (GUI) must be open beforehand for GetActiveObject to work.
I understand
#4- Construct the AutoLISP expression that loads AutoLISP files
command_str = '(load ' + '"' + lispfile + '")' + " "
#5-Execute the AutoLISP expression
print "Sending AutoLISP Expression ..."
print "Expression: " + command_str
doc.SendCommand("(setq *LOAD_SECURITY_STATE* (getvar 'SECURELOAD)) ")
doc.SendCommand("(setvar \"SECURELOAD\" 0) ")
doc.SendCommand(command_str)
doc.SendCommand("(setvar \"SECURELOAD\" *LOAD_SECURITY_STATE*) ")
print "AutoLISP Expression is successfuly sent"
print "########"
loads lisp file . But I don't understand how the input arguments have to be passed
input:
(graph
'((75 25) (115 45) (90 60) (10 5) (45 0) (45 55) (0 25))
'(1 1 1 1 2 2 3 4 4 5 6)
'(2 3 4 5 3 6 6 5 7 7 7)
)
I'd like to request for clarifications on the same.
As I told before, have no experience with it.
I guess Acad should be started.
After you load a script try to add
doc.SendCommand("
(graph
'((75 25) (115 45) (90 60) (10 5) (45 0) (45 55) (0 25))
'(1 1 1 1 2 2 3 4 4 5 6)
'(2 3 4 5 3 6 6 5 7 7 7)
)
")
Miljenko Hatlak
Generate a script file and launch it in AutoCAD.
For each drawing, in python write the following lines into a .scr-file (with your files, pts, sls and such of course):
open
c:\files\drawing.dwg
(load "c:\\lisps\\graph.lsp")
(graph
'((75 25) (115 45) (90 60) (10 5) (45 0) (45 55) (0 25))
'(1 1 1 1 2 2 3 4 4 5 6)
'(2 3 4 5 3 6 6 5 7 7 7)
)
saveas dxf 16
c:\files\drawing.dxf
close
Just concatenate all into same .scr-file.
To convert tuples and lists to string:
def iter_to_lisp_string (list_or_tuple):
return "(" + " ".join(map(str,list_or_tuple)) + ")"
pts_string = "'" + iter_to_lisp_string(map(iter_to_lisp_string , [(75, 25), (115, 45), (90, 60), (10, 5), (45, 0), (45, 55), (0, 25)]))
sls_string = "'" + iter_to_lisp_string([1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6])
tls_string = "'" + iter_to_lisp_string([2, 3, 4, 5, 3, 6, 6, 5, 7, 7, 7])
graph_command_string = iter_to_lisp_string(["graph", pts_string, sls_string, tls_string])
To launch script from powershell, issue command
<path to acad.exe> /b <path to script.scr>
For example (question marks in place of spaces):
C:\Program?files\AutoDesk\AutoCAD?2018\acad.exe /b c:\files\script.scr
To launch from python, I believe you have to call subprocess similarly to above, but I'm not sure.
This is VBA but would be similar for python if Autocad is not running then open it.
Look at post #2 also.
'Check if AutoCAD application is open. If is not opened create a new instance and make it visible.
On Error Resume Next
Set acadApp = GetObject(, "AutoCAD.Application")
If acadApp Is Nothing Then
Set acadApp = CreateObject("AutoCAD.Application")
acadApp.Visible = True
End If
Hi,
could you please explain a bit on
def iter_to_lisp_string (list_or_tuple): return "(" + " ".join(map(str,list_or_tuple)) + ")"
It is not clear to me why this function is used. I've written the rest to .scr file from python
It is just a helper function to convert python tuples and lists into a format that autolisp understands. [(75,25),...] into "((75 25) ...)", [1,1,...] into "(1 1 ...)"
graph_command_string is the "(graph ... ... ...)" part of the .scr, you may write it to the script or send the command to autocad, I think that would also work.
You don't need to use it if you like to do the conversion from tuples and lists into lisp lists any other way.
@Anonymous @Sea-Haven
I've put together the following based on the suggestions
"""
This code passes inputs from python to autocad
ref: https://stackoverflow.com/questions/48794935/batch-run-autolisp-with-python
ref: https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/how-to-interface-with-autocad-from-python/m-p/9768816/highlight/false#M404952
"""
import comtypes.client
from comtypes import COMError
from comtypes.client import CreateObject, GetModule, GetActiveObject
from settings import\
GRAPH_LISP_FILE,\
GRAPH_SRC_FILE,\
GRAPH_DWG_FILE,\
GRAPH_DXF_FILE
def write_src(graph):
with open(GRAPH_SRC_FILE, 'w') as outfile:
outfile.write("open\n" +
f"{GRAPH_DWG_FILE}" + "\n"
rf'(load "{GRAPH_LISP_FILE}")' + "\n"
f"{graph}\n" +
"saveas dxf 16\n" +
rf"{GRAPH_DXF_FILE}" +"\n"+
"close"
)
pass
def iter_to_lisp_string (list_or_tuple):
return "(" + " ".join(map(str, list_or_tuple)) + ")"
if __name__ == '__main__':
pts_string = "'" + iter_to_lisp_string(map(iter_to_lisp_string, [(75, 25), (115, 45), (90, 60), (10, 5), (45, 0), (45, 55), (0, 25)]))
sls_string = "'" + iter_to_lisp_string([1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6])
tls_string = "'" + iter_to_lisp_string([2, 3, 4, 5, 3, 6, 6, 5, 7, 7, 7])
graph_command_string = iter_to_lisp_string(["graph", pts_string, sls_string, tls_string])
write_src(graph=graph_command_string)
try:
acad = GetActiveObject("AutoCAD.Application")
print("AutoCAD is Active")
except(OSError, COMError): # If AutoCAD isn't running, run it
acad = CreateObject("AutoCAD.Application", dynamic=True)
print("AutoCAD is successfuly Opened")
But the following error occurs
_ole32.CoCreateInstance(byref(clsid), punkouter, clsctx, byref(iid), byref(p))
File "_ctypes/callproc.c", line 935, in GetResult
OSError: [WinError -2146959355] Server execution failed
I'd like to know how to solve this error and how to proceed after this and send commands to AutoCAD.
Many thanks,
Deepa
I checked now, AutoCAD script can be launched without com by using subprocess:
import subprocess
subprocess.run(["C:\\Program Files\\Autodesk\\AutoCAD 2018\\acad.exe", "/b", "D:\\test\\asdf.scr"])
# or prior to python 3.5
subprocess.call(["C:\\Program Files\\Autodesk\\AutoCAD 2018\\acad.exe", "/b", "D:\\test\\asdf.scr"])
Path to acad.exe, /b is commandline switch for running a script and after that is your script file.
Python will resume after AutoCAD is closed, so for the last file you want to process, write "quit" instead of "close" to the .scr. Otherwise AutoCAD will stay open and python cannot resume, because it sees the subprocess is still running. If you always process one drawing at a time, just replace "close" with "quit" in write_scr.
Thank you, I tried
pts_string = "'" + iter_to_lisp_string(map(iter_to_lisp_string, [(75, 25), (115, 45), (90, 60), (10, 5), (45, 0), (45, 55), (0, 25)]))
sls_string = "'" + iter_to_lisp_string([1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6])
tls_string = "'" + iter_to_lisp_string([2, 3, 4, 5, 3, 6, 6, 5, 7, 7, 7])
graph_command_string = iter_to_lisp_string(["graph", pts_string, sls_string, tls_string])
write_src(graph=graph_command_string)
import subprocess
subprocess.run(["C:\\Program Files\\Autodesk\\AutoCAD 2019\\acad.exe", "/b", "E:\\df\\graph.scr"])
This opens the AutoCAD application, but the command in .src isn't sent. It just opens the drawing file. I
also tried via com
pts_string = "'" + iter_to_lisp_string(map(iter_to_lisp_string, [(75, 25), (115, 45), (90, 60), (10, 5), (45, 0), (45, 55), (0, 25)]))
sls_string = "'" + iter_to_lisp_string([1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6])
tls_string = "'" + iter_to_lisp_string([2, 3, 4, 5, 3, 6, 6, 5, 7, 7, 7])
graph_command_string = iter_to_lisp_string(["graph", pts_string, sls_string, tls_string])
write_src(graph=graph_command_string)
try:
acad = GetActiveObject("AutoCAD.Application")
print("AutoCAD is Active")
except(OSError, COMError): # If AutoCAD isn't running, run it
acad = CreateObject("AutoCAD.Application", dynamic=True)
print("AutoCAD is successfuly Opened")
#3- Open the drawing file
print("Opening Drawing File ...")
doc = acad.Documents.Open(GRAPH_DWG_FILE)
print("Drawing is successsfuly Opened")
# 4- Construct the AutoLISP expression that loads AutoLISP files
command_str = graph_command_string # '(load ' + '"' + graph_command_string + '")' + " "
# 5-Execute the AutoLISP expression
print("Sending AutoLISP Expression ...")
print("Expression: " + command_str)
doc.SendCommand("(setq *LOAD_SECURITY_STATE* (getvar 'SECURELOAD)) ")
doc.SendCommand("(setvar \"SECURELOAD\" 0) ")
doc.SendCommand(command_str)
doc.SendCommand("(setvar \"SECURELOAD\" *LOAD_SECURITY_STATE*) ")
print("AutoLISP Expression is successfuly sent")
#6- Save and Close the drawing file and AutoCAD application
doc.Save()
doc.Close()
acad.Quit()
print("Process Finished")
This sends the command, I can view the command in the command line but creates the drawing only after I manually hit enter. I don't want to do this manually.
Could you please let me know how to create the dxf file with drawing automatically?
Can't find what you're looking for? Ask the community or share your knowledge.