# Plans2DWG (Iron \> CPython3)

**URL:** <https://forum.dynamobim.com/t/plans2dwg-iron-cpython3/101566>\
**Category:** Uncategorized\
**Tags:** dwg, cpython3\
**Created:** [June 3, 2024, 1:17pm UTC](https://forum.dynamobim.com/t/plans2dwg-iron-cpython3/101566 "2024-06-03T13:17:02Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![snowyweston](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/snowyweston/32/19412_2.png) [@snowyweston](https://forum.dynamobim.com/u/snowyweston)\
**Post date:** [June 3, 2024, 1:17pm UTC](https://forum.dynamobim.com/t/plans2dwg-iron-cpython3/101566/1 "2024-06-03T13:17:02Z")

</div>

the year is 2024  
and some folk are _still_ still asking for .dwg files!

…and I am picking up a very old script (that we had, working, in Revit 2019) that used the bulk of @Konrad_K_Sobon’s (IronPython) code from this thread:

> [@Export View Set To DWG](https://forum.dynamobim.com/t/export-view-set-to-dwg/5441/3):
>
> The graph is quite big for an image so I have attached the DYN file. At the moment it is working on all gridlines but once we get the agreed list on an excel spreadsheet it will use that to determine the sections to be created. As to the Building coder link I don’t realy have any experience with python or coding so it is a little beyond my skills at the moment Thanks Darren [Section By Gridline.dyn](https://forum.dynamobim.com/uploads/short-url/fVxSA6gBLB2aImAdbGQQUndlJo5.dyn) (168.3 KB)

```auto
# Copyright(c) 2016, Konrad K Sobon
# @arch_laboratory, http://archi-lab.net

# Import Element wrapper extension methods
import clr
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

import System
from System.Collections.Generic import *

import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)

#The inputs to this node will be stored as a list in the IN variable.
dataEnteringNode = IN

def ProcessList(_func, _list):
    return map( lambda x: ProcessList(_func, x) if type(x)==list else _func(x), _list )

def ProcessParallelLists(_func, *lists):
	return map( lambda *xs: ProcessParallelLists(_func, *xs) if all(type(x) is list for x in xs) else _func(*xs), *lists )

def Unwrap(item):
	return UnwrapElement(item)

folderPath = IN[0]

if isinstance(IN[1], list):
	views = ProcessList(Unwrap, IN[1])
else:
	views = list(Unwrap(IN[1]))

if isinstance(IN[2], list):
	names = IN[2]
else:
	names = list(IN[2])

RunIt = IN[3]

def ExportDwg(name, view, folder = folderPath):
	options = DWGExportOptions()
	options.SharedCoords = True #sharedCoords
	options.LayerMapping = "L:\SOFTWARE\REVIT\Library\Shared\Export_Definitions\A_PT_RVT-to-DWG.txt"
	options.Colors = options.Colors.TrueColorPerView
	views = List[ElementId]()
	views.Add(view.Id)
	result = doc.Export(folder, name, views, options)
	return result

if RunIt:
	try:
		errorReport = None
		# run export
		ProcessParallelLists(ExportDwg, names, views)
		
	except:
		# if error accurs anywhere in the process catch it
		import traceback
		errorReport = traceback.format_exc()
else:
	errorReport = "Please set the RunIt to True!"

#Assign your output to the OUT variable
if errorReport == None:
	OUT = 0
else:
	OUT = errorReport

```

w/ a few modifications of my own, namely added:

- shared coord export (ln56)
- layer-mapping (ln57)\*
- color options (ln58)  
(that I sourced from scavenging code elsewhere)

\*_which I’ve removed from both .dyn files uploaded here as that points to a local resource wouldbe testers won’t have_

* * *

thing is, once in Revit 2023, having switched the script-node to CPython3  
(in the lazy, fingers-crossed hope that that would be all that’s needed)  
**the Revit 2023 version does not output any .dwg files**.

Peering through the code late last Friday afternoon I spotted ln25 calling specifiically on a library:  
`pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'`  
… and thought, _“aha! that’s the block!”_ had a bit of a cry on Twitargh (hey @solamour !) then sought to swap that out

but alas even after “learning” the CPython3 libraries live elsewhere/behave a bit differently - care of this:

> **[Customizing Dynamo's Python 3 installation](https://github.com/DynamoDS/Dynamo/wiki/Customizing-Dynamo%27s-Python-3-installation)**
>
> Open Source Graphical Programming for Design. Contribute to DynamoDS/Dynamo development by creating an account on GitHub.

swapping in either

```auto
C:\Users\Kieren.Porter\AppData\Local\python-3.9.12-embed-amd64\
C:\Users\Kieren.Porter\AppData\Local\python-3.9.12-embed-amd64\python39.zip

```

didn’t do anything!?  
nor did removing that whole chunk (that @Mark.Ackerley _appeared_ to allude to)  
(which I’ve left in in the uploaded copies)

* * *

presumably, there’s something more (not) going-on here - and this is one of those perfect-storm moments folk like me deserve to run into when blindly using found-code - but if anyone could offer up any insight what could get this over the line, and spitting out .dwg files “again”, I’d be most grateful!!!

PS:  
the quick-test .rvt models for 2019 & 2023 uploaded here should spit out 3No. .dwg files (using their respective .dyn)  
 ![success2019](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/f/c/fc7a15b7e8aacb3f9b0498376c3e49c7ccf4320f.png)  
[Project\_2019.rvt](https://forum.dynamobim.com/uploads/short-url/lu2SHOBLxoT2m2RYzWipqTLrPbD.rvt) (460 KB)  
[Plans to DWG\_2019\_no-mapping.dyn](https://forum.dynamobim.com/uploads/short-url/76JmXzCVxH06Z2XzfYr8iypnhgW.dyn) (38.8 KB)  
[Project\_2023.rvt](https://forum.dynamobim.com/uploads/short-url/t5lXqJOJOmWvXWO8zO0lyNrmVjo.rvt) (480 KB)  
[Plans to DWG\_2023\_no-mapping.dyn](https://forum.dynamobim.com/uploads/short-url/i5kSbapxsXVAX69N0iGsy2ACQeC.dyn) (41.2 KB)

---

<div class="post-metadata">

**Author:** ![Mark.Ackerley](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/mark.ackerley/32/79310_2.png) [@Mark.Ackerley](https://forum.dynamobim.com/u/Mark.Ackerley)\
**Post date:** [June 3, 2024, 2:03pm UTC](https://forum.dynamobim.com/t/plans2dwg-iron-cpython3/101566/2 "2024-06-03T14:03:24Z")

</div>

Hey,

I hit the ![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/4/1/4124109ff1aadf0e74213616b589d9d6749d329a.png) button in the python script editor, and commented out the line 58 and it worked for me?

```auto
options.Colors = options.Colors.TrueColorPerView

```

I’m not quite sure why, but options.Colors returns 0 instead of the enumeration?

I’ll dig around and see if I can work out why 🙂

Hope that helps,

Mark

---

<div class="post-metadata">

**Author:** ![jacob.small](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/jacob.small/32/161030_2.png) [@jacob.small](https://forum.dynamobim.com/u/jacob.small)\
**Post date:** [June 3, 2024, 2:06pm UTC](https://forum.dynamobim.com/t/plans2dwg-iron-cpython3/101566/3 "2024-06-03T14:06:22Z")

</div>

> [@Mark.Ackerley](#):
>
> I’m not quite sure why, but options.Colors returns 0 instead of the enumeration?

Enums are not fully supported, so you have to do a round-about way to get them. There are several examples on the forum which can be found via search. 🙂

---

<div class="post-metadata">

**Author:** ![snowyweston](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/snowyweston/32/19412_2.png) [@snowyweston](https://forum.dynamobim.com/u/snowyweston)\
**Post date:** [June 3, 2024, 2:08pm UTC](https://forum.dynamobim.com/t/plans2dwg-iron-cpython3/101566/4 "2024-06-03T14:08:46Z")

</div>

ooo

I did (after posting) pull out all my additions - but didn’t get any different result (interestingly, I get a 0 return even on succesful runs of the 2019 version?)

tbh I’ll happily abandon the additional switches (well, all except the shared.coords one, as that’s really the whole point we need/want the automation) if it gets the thing working

---

<div class="post-metadata">

**Author:** ![Mark.Ackerley](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/mark.ackerley/32/79310_2.png) [@Mark.Ackerley](https://forum.dynamobim.com/u/Mark.Ackerley)\
**Post date:** [June 3, 2024, 2:12pm UTC](https://forum.dynamobim.com/t/plans2dwg-iron-cpython3/101566/5 "2024-06-03T14:12:57Z")

</div>

> [@snowyweston](#):
>
> ```auto
> if errorReport == None:
> OUT = 0
> 
> ```

That’s how it’s setup 🙂

You could change to OUT = ‘woop\_woop’ or perhaps append ‘result’ to an output list to confirm the files created? Something similar anyway 🙂

Mark

```auto
# Copyright(c) 2016, Konrad K Sobon
# @arch_laboratory, http://archi-lab.net

# Import Element wrapper extension methods
import clr
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

import System
from System.Collections.Generic import *

import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)

#The inputs to this node will be stored as a list in the IN variable.
dataEnteringNode = IN

def ProcessList(_func, _list):
    return [ProcessList(_func, x) if type(x)==list else _func(x) for x in _list]

def ProcessParallelLists(_func, *lists):
        return list(map( lambda *xs: ProcessParallelLists(_func, *xs) if all(type(x) is list for x in xs) else _func(*xs), *lists ))

def Unwrap(item):
        return UnwrapElement(item)

folderPath = IN[0]

if isinstance(IN[1], list):
        views = ProcessList(Unwrap, IN[1])
else:
        views = list(Unwrap(IN[1]))

if isinstance(IN[2], list):
        names = IN[2]
else:
        names = list(IN[2])

RunIt = IN[3]

output = []

def ExportDwg(name, view, folder = folderPath):
        options = DWGExportOptions()
        options.SharedCoords = True #sharedCoords
        options.LayerMapping = "L:\SOFTWARE\REVIT\Library\Shared\Export_Definitions\A_PT_RVT-to-DWG.txt"
        options.Colors = ExportColorMode.TrueColorPerView
        views = List[ElementId]()
        views.Add(view.Id)
        result = doc.Export(folder, name, views, options)
        return name

if RunIt:
        try:
                errorReport = None
                # run export
                output.append(ProcessParallelLists(ExportDwg, names, views))
                

        except:
                # if error accurs anywhere in the process catch it
                import traceback
                errorReport = traceback.format_exc()
else:
        errorReport = "Please set the RunIt to True!"

#Assign your output to the OUT variable
if errorReport == None:
        OUT = output
else:
        OUT = errorReport

```

---

<div class="post-metadata">

**Author:** ![Mark.Ackerley](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/mark.ackerley/32/79310_2.png) [@Mark.Ackerley](https://forum.dynamobim.com/u/Mark.Ackerley)\
**Post date:** [June 3, 2024, 2:17pm UTC](https://forum.dynamobim.com/t/plans2dwg-iron-cpython3/101566/6 "2024-06-03T14:17:31Z")

</div>

This seems to work…

```auto
options.Colors = ExportColorMode.TrueColorPerView

```

---

<div class="post-metadata">

**Author:** ![snowyweston](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/snowyweston/32/19412_2.png) [@snowyweston](https://forum.dynamobim.com/u/snowyweston)\
**Post date:** [June 3, 2024, 2:24pm UTC](https://forum.dynamobim.com/t/plans2dwg-iron-cpython3/101566/7 "2024-06-03T14:24:24Z")

</div>

![fixed](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/f/1/f1ca4b64758f03d4c63da5959d0cc87d5d60cfd9.png)  
confirmed! bless you Mark!!!

PS:  
i wasn’t even aware of the 2-to-3 auto-fix-thingy - so that’s a real plus to know!!!

 ![2-to-3](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/b/e/be35b2da4c7f1d34ea949235a6144babf9f050fc.png)

---

<div class="post-metadata">

**Author:** ![solamour](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/solamour/32/153516_2.png) [@solamour](https://forum.dynamobim.com/u/solamour)\
**Post date:** [June 3, 2024, 4:22pm UTC](https://forum.dynamobim.com/t/plans2dwg-iron-cpython3/101566/8 "2024-06-03T16:22:56Z")

</div>

Glad it’s working now 😃 Big-ups to @Mark.Ackerley!

Also, we’re actively working on improving the CPython3 implementation this quarter, so expect some of the “Workarounds” to disappear in liue of… better things 🙂 Will never be full parity with IronPython as they are different implementations, but it will definitely be better.
