Revit Python Shell: How to get Type names of 'Pipe Types' Family with no instances in project? - revit-api

End goal is to pass the ElementId of the PipeType I want (Plex Wire) to Pipe.Create, but I don't know how to select the correct PipeType ElementId in a project with no Pipe instances to inspect.
In a test project, I have used Transfer Project Standards to bring over the PipeType I want to use, and manually created a few Pipe instances to inspect...
>>> import Autodesk.Revit as R
>>> types=R.DB.FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_PipeCurves).WhereElementIsElementType().ToElements()
>>> elems=R.DB.FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_PipeCurves).WhereElementIsNotElementType().ToElements()
>>> for i in elems: print(i.Name)
...
Default
Default
Default
Plex Wire
>>> for i in types: print(i.Name)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
AttributeError: Name
...but as I mentioned, I'd like to be able to use Pipe.Create from a project which contains the desired PipeTypes (from a Project Template), but has no pre-existing Pipe instances.
Thanks

I got Jeremy's 'transaction trick' to work (see below). Any critique on my code is appreciated, Thanks!
import Autodesk.Revit as R
pipeTypeNames={}
def GetPipeTypeNames():
types=R.DB.FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_PipeCurves).WhereElementIsElementType().ToElements()
pipingSystemTypes=R.DB.FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_PipingSystem).ToElements()
levels=R.DB.FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Levels).WhereElementIsNotElementType().ToElements()
pipeDoc=doc
pipeSystem=pipingSystemTypes[0].Id
pipeLevel=levels[0].Id
points=[]
transaction=R.DB.Transaction(doc,'Get Pipe Type Names')
transaction.Start()
for t in range(len(types)):
pipeType=types[t].Id
points.append((R.DB.XYZ(0,t,0),R.DB.XYZ(10,t,0)))
R.DB.Plumbing.Pipe.Create(pipeDoc,pipeSystem,pipeType,pipeLevel,points[t][0],points[t][1])
pipeElems=R.DB.FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_PipeCurves).WhereElementIsNotElementType().ToElements()
for p in pipeElems:
pipeTypeNames[p.Name]=p.PipeType
transaction.RollBack()
GetPipeTypeNames()

Use the ElementType FamilyName property introduced in Revit 2015.
Before that, the simplest option used to be to use the temporary transaction trick: open a transaction, insert a dummy instance, grab the desired name, and roll back the transaction.

Related

Revit Python Shell / Revit Python Wrapper - get Element name by id

I'm trying to get the name of an element by way the ID using Revit python wrapper in Revit python shell but I'm having issues. I am typically able to do it using c# but rpw is new to me.
I try:
doc.GetElement(2161305).name or doc.GetElement(2161305).Name
and I get this error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: expected Reference, got int
I've looked a bit through the docs and watched some of the videos but haven't found anything that has covered this. I'm sure its easy, I'm just not not finding the answer.
Any help / direction is appreciated.
Got to answer my own question again.
>>> from rpw import db
>>> element = db.Element(SomeElement)
>>> element = db.Element.from_id(ElementId)
>>> element = db.Element.from_int(Integer) # this one worked for me
You need to cast the integer to an ElementId. The GetElement has three overloads. None of them takes an int, so you need to cast it to clarify which one is intended. Please read the GetElement documentation.

'DataFrame' object has no attribute 'get_value' in Pandas

Just learning python now, have very weak programming background.
I keep getting the error: 'DataFrame' object has no attribute 'get_value' using python 3.8.
The file is a random file I downloaded from the internet just to learn how to use dataframes and pandas. The object here is to pull a specific value out of the dataframe, so that I can manipulate it later.
import pandas as pd
pb_list = [] pb_list =
pd.read_csv(r"PB2010plus.csv") print(pb_list)
print(type(pb_list))
print(pb_list.get_value(1047, 'Winning Numbers'))
here's the error line
Traceback (most recent call last): File
"I:/Python/PycharmProjects/Learning Python 1/probabilityfunsheet.py",
line 8, in
print(pb_list.get_value(1047, 1)) File "C:\Users\greyb\AppData\Local\Programs\Python\Python38-32\lib\site-packages\pandas\core\generic.py",
line 5274, in getattr
return object.getattribute(self, name) AttributeError: 'DataFrame' object has no attribute 'get_value'
I am using pycharm, and did some searching, came across https://www.geeksforgeeks.org/python-pandas-dataframe-get_value/ which is where I got the idea as a potential solution for my 'problem'.
Starting it with an underscore worked for me
df._get_value(index,'name')
A good habit while reading data frames in Python is setting them as a variable:
import pandas as pd
pb_list = pd.read_csv("PB2010plus.csv")
Thus, to visualize them you won't need to print them, but you will just need to recall the variable pb_list.
# take a look to the dataframe
pb_list
# check the dataframe's type
type(pb_list)
# access to 1047 row index inside the Winning Numbers column
pb_list.get_value(1047, 'Winning Numbers')
However get_value has been deprecated and will be removed in a future release. Please use .at[] or .iat[] accessors instead.
Regarding your question. If you want to store the value that you are searching for in a variable to manipulate it in the future, here's the code:
# storing the desired value in target_value
target_value = pb_list.get_value(1047, 'Winning Numbers')
Please try using
df._get_value()
instead of
df.get_value()
The get_values method for a DataFrame was deprecated. Use values() instead. More info here
You don't need to put the result into a list pd_list = [] This code will give you an empty list and fill out this list with for loop in general. Try to remove that code and see what happens. Hope this helps.

Finding the source code of methods implemented in C?

Please note I am asking this question for informational purposes only
I know the title sound like a duplicate of Finding the source code for built-in Python functions?. But let me explain.
Say for example, I want to find the source code of most_common method of collections.Counter class. Since the Counter class is implemented in python I could use the inspect module get it's source code.
ie,
>>> import inspect
>>> import collections
>>> print(inspect.getsource(collections.Counter.most_common))
This will print
def most_common(self, n=None):
'''List the n most common elements and their counts from the most
common to the least. If n is None, then list all element counts.
>>> Counter('abcdeabcdabcaba').most_common(3)
[('a', 5), ('b', 4), ('c', 3)]
'''
# Emulate Bag.sortedByCount from Smalltalk
if n is None:
return sorted(self.items(), key=_itemgetter(1), reverse=True)
return _heapq.nlargest(n, self.items(), key=_itemgetter(1))
So if the method or class is implemented in C inspect.getsource will raise TypeError.
>>> my_list = []
>>> print(inspect.getsource(my_list.append))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\abdul.niyas\AppData\Local\Programs\Python\Python36-32\lib\inspect.py", line 968, in getsource
lines, lnum = getsourcelines(object)
File "C:\Users\abdul.niyas\AppData\Local\Programs\Python\Python36-32\lib\inspect.py", line 955, in getsourcelines
lines, lnum = findsource(object)
File "C:\Users\abdul.niyas\AppData\Local\Programs\Python\Python36-32\lib\inspect.py", line 768, in findsource
file = getsourcefile(object)
File "C:\Users\abdul.niyas\AppData\Local\Programs\Python\Python36-32\lib\inspect.py", line 684, in getsourcefile
filename = getfile(object)
File "C:\Users\abdul.niyas\AppData\Local\Programs\Python\Python36-32\lib\inspect.py", line 666, in getfile
'function, traceback, frame, or code object'.format(object))
TypeError: <built-in method append of list object at 0x00D3A378> is not a module, class, method, function, traceback, frame, or code object.
So my question is, Is there is any way(or Using third party package?) that we can find the source code of class or method implemented in C as well?
ie, something like this
>> print(some_how_or_some_custom_package([].append))
int
PyList_Append(PyObject *op, PyObject *newitem)
{
if (PyList_Check(op) && (newitem != NULL))
return app1((PyListObject *)op, newitem);
PyErr_BadInternalCall();
return -1;
}
No, there is not. There is no metadata accessible from Python that will let you find the original source file. Such metadata would have to be created explicitly by the Python developers, without a clear benefit as to what that would achieve.
First and foremost, the vast majority of Python installations do not include the C source code. Next, while you could conceivably expect users of the Python language to be able to read Python source code, Python's userbase is very broad and a large number do not know C or are interested in how the C code works, and finally, even developers that know C can't be expected to have to read the Python C API documentation, something that quickly becomes a requirement if you want to understand the Python codebase.
C files do not directly map to a specific output file, unlike Python bytecode cache files and scripts. Unless you create a debug build with a symbol table, the compiler doesn't retain the source filename in the generated object file (.o) it outputs, nor will the linker record what .o files went into the result it produces. Nor do all C files end up contributing to the same executable or dynamic shared object file; some become part of the Python binary, others become loadable extensions, and the mix is configurable and dependent on what external libraries are available at the time of compilation.
And between makefiles, setup.py and C pre-propressor macros, the combination of input files and what lines of source code are actually used to create each of the output files also varies. Last but not least, because the C source files are no longer consulted at runtime, they can't be expected to still be available in the same original location, so even if there was some metadata stored you still couldn't map that back to the original.
So, it's just easier to just remember a few base rules about how the Python C-API works, then map that back to the C code with a few informed code searches.
Alternatively, download the Python source code and create a debug build, and use a good IDE to help you map symbols and such back to source files. Different compilers, platforms and IDEs have different methods of supporting symbol tables for debugging.
There could be a way if you had the whole debug information (which are usually stripped).
Then you would get to the so or pyd, and use platform specific tools to extract the debug information (stored in the so or in the pdb on Windows) for the required function. You may want to have a look at DWARF information for Linux (on Windows, there is no documentation AFAIK).

Python3 check if ip address is global

I'm trying to use python's "new" is_global method to determine, wether an ip address is allocated for public networks (https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Address.is_global). However, this does not work:
>>> import ipaddress
>>> ip = ipaddress.IPv4Address('192.0.2.1')
>>> ip.is_private
True
>>> ip.is_reserved
False
>>> ip.is_global
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'IPv4Address' object has no attribute 'is_global'
>>>
As shown above, the other methods like is_private work fine. I'm using python 3.5.1.
Any insights?
I had a look at a bug report here and went to check the ipaddress.py module. While there exists an is_global attribute it is clearly not implemented and the bug report remains open and unresolved from Spring 2014 so I wouldn't hold my breath. If necessary you could get in touch with someone from the original bug report and get a status update.
UPDATE: According to user #galgalesh, at the time of writing this question, the is_global attribute was not implemented. That bug was resolved in Python 3.5 on 2016-06-11.
Attribute is_global is implemented as of Python 3.5+.

Appending to clipboard

I feel like I have been asking a lot of questions the last couple days but I really need help with this one. First of its my 3rd day writing code and python is the language of choice that I chose to learn to code.
OK I made this converter that converts units of measurement from mm to inches (and also converts surface finishes) I then want it to copy the converted number (taken out to the third decimal place) to the clipboard so I can paste it in another program. I am trying to do this using tkinter but I keep getting the error message
Traceback (most recent call last):
File "C:\Pygrams\Converter.py", line 104, in <module>
clipboard_append(final_form)
NameError: name 'clipboard_append' is not defined
Here is the code (only posting the part I am having trouble with) im using (assume that variables such as Results are defined elsewhere.
from tkinter import Tk
final_form = ("%.3f" % Results)
final_form2 = str(final_form)
r = Tk()
r.withdraw()
r.clipboard_clear()
clipboard_append(finalform2)
r.destroy()
What am I doing wrong?
You're calling clipboard_append(finalform2) when you should be calling r.clipboard_append(finalform2)

Resources