Closed eechhx closed 2 years ago
And similar results from using just the SWIG interface methods. Pardon my lack of error checking in the example below.
import gphoto2 as gp
import time
camera = gp.check_result(gp.gp_camera_new())
context = gp.gp_context_new()
config = gp.check_result(gp.gp_camera_get_config(camera, context))
prop = config.get_child_by_id(20)
print("prop by id", prop.get_name())
prop = config.get_child_by_name("whitebalance")
print("prop by name", prop.get_name())
config = gp.check_result(gp.gp_camera_get_config(camera, context))
prop = config.get_child_by_id(20)
print("prop by id", prop.get_name())
prop = config.get_child_by_name("whitebalance")
print("prop by name", prop.get_name())
prop by id whitebalance
prop by name whitebalance
Traceback (most recent call last):
File "error_test.py", line 14, in <module>
prop = config.get_child_by_id(20)
gphoto2.GPhoto2Error: [-2] Bad parameters
But when reinitializing the camera objects, no exceptions are thrown.
import gphoto2 as gp
import time
camera = gp.check_result(gp.gp_camera_new())
context = gp.gp_context_new()
config = gp.check_result(gp.gp_camera_get_config(camera, context))
prop = config.get_child_by_id(20)
print("prop by id", prop.get_name())
prop = config.get_child_by_name("whitebalance")
print("prop by name", prop.get_name())
camera = gp.check_result(gp.gp_camera_new())
context = gp.gp_context_new()
config = gp.check_result(gp.gp_camera_get_config(camera, context))
prop = config.get_child_by_id(20)
print("prop by id", prop.get_name())
prop = config.get_child_by_name("whitebalance")
print("prop by name", prop.get_name())
prop by id whitebalance
prop by name whitebalance
prop by id whitebalance
prop by name whitebalance
However the workaround is only useful when you're reinitializing the camera within the same scope. Reinitializing fails when you make function calls (which makes sense).
import gphoto2 as gp
def test_func():
camera = gp.Camera()
camera.init()
config = camera.get_config()
camera = gp.Camera()
camera.init()
config = camera.get_config()
test_func()
Traceback (most recent call last):
File "error_test.py", line 14, in <module>
test_func()
File "error_test.py", line 6, in test_func
camera.init()
gphoto2.GPhoto2Error: [-60] Could not lock the device
Thus, I'm not sure if the workaround is ideal. (But you can always wrap everything up as a class!)
I'm not sure if calling get_config
twice is supported, or why you'd want to do it. The first time you call it all the camera's config values are copied to a tree of "widgets", calling it again will just copy the same values to another tree of widgets. Setting a value on one tree won't affect the other, and won't affect the camera until you call set_config
to copy the (changed) values back to the camera.
After calling set_config
you might need to delete all references to the config widgets before calling get_config
again, but I'm not sure.
However, the Canon config stuff has changed in the latest release of libgphoto2, so you might have found a bug. Try going back to python-gphoto2==2.3.0 and see what happens. https://github.com/gphoto/libgphoto2/issues/352#issuecomment-933401683
However, the Canon config stuff has changed in the latest release of libgphoto2, so you might have found a bug. Try going back to python-gphoto2==2.3.0 and see what happens.
Same error outputs as gphoto2==2.3.2
listed above.
I'm not sure if calling
get_config
twice is supported, or why you'd want to do it.
i.e. - the reason why I would call get_config()
twice is because despite set_config()
passing error checks and returning 0
, if the camera is physically set in a different mode (AUTO
), attempting to set white balance shows the value to be set correctly after setting the config and calling get_value()
. However we know that's not the case due to the camera being in a specific mode. I would just like to account for these situations, which is why I call to get updated configs as a sanity check.
import gphoto2 as gp
import time
camera = gp.Camera()
camera.init()
config = camera.get_config()
property = config.get_child_by_name("whitebalance")
print("White balance readonly value", property.get_readonly())
print("White balance value currently", property.get_value())
property.set_value("Daylight")
camera.set_config(config)
print("White balance value after setting", property.get_value())
camera = gp.Camera()
camera.init()
config = camera.get_config()
property = config.get_child_by_name("whitebalance")
print("White balance value after reinit", property.get_value())
White balance readonly value 0
White balance value currently Automatic
White balance value after setting Daylight
White balance value after reinit Automatic
After calling
set_config
you might need to delete all references to the config widgets before callingget_config
again, but I'm not sure.
The error comes from switching how you get a child property. As to why someone would want to do this, who knows. But my assumption would be that it should be fairly dynamic. Prior to the del
call, if you call get_child_by_name()
and then get_child_by_name()
or get_child_by_label()
, it passes the test case. However if you call get_child_by_name()
and then
attempt to call get_child_by_id()
, an exception is raised. This is the behaviour I'm a bit confused about.
Calling get_child_by_name()
and then get_child_by_id()
camera = gp.Camera()
camera.init()
config = camera.get_config()
property = config.get_child_by_name("whitebalance")
print("White balance readonly value", property.get_readonly())
print("White balance value currently", property.get_value())
property.set_value("Daylight")
camera.set_config(config)
print("White balance value after setting", property.get_value())
del config
config = camera.get_config()
property = config.get_child_by_id(20)
print("White balance value after reinit", property.get_value())
White balance readonly value 0
White balance value currently Automatic
White balance value after setting Daylight
Traceback (most recent call last):
File "error_test.py", line 18, in <module>
property = config.get_child_by_id(20)
gphoto2.GPhoto2Error: [-2] Bad parameters
Calling get_child_by_id()
and then get_child_by_name()
# Camera initialization not shown
property = config.get_child_by_id(20)
print("White balance readonly value", property.get_readonly())
print("White balance value currently", property.get_value())
property.set_value("Daylight")
camera.set_config(config)
print("White balance value after setting", property.get_value())
del config
config = camera.get_config()
property = config.get_child_by_name("whitebalance")
print("White balance value after reinit", property.get_value())
White balance readonly value 0
White balance value currently Automatic
White balance value after setting Daylight
White balance value after reinit Automatic
Calling get_child_by_id()
and then get_child_by_label()
# Camera initialization not shown
property = config.get_child_by_id(20)
print("White balance readonly value", property.get_readonly())
print("White balance value currently", property.get_value())
property.set_value("Daylight")
camera.set_config(config)
print("White balance value after setting", property.get_value())
del config
config = camera.get_config()
property = config.get_child_by_label("WhiteBalance")
print("White balance value after reinit", property.get_value())
White balance readonly value 0
White balance value currently Automatic
White balance value after setting Daylight
White balance value after reinit Automatic
Calling get_child_by_label()
and then get_child_by_id()
# Camera initialization not shown
property = config.get_child_by_label("WhiteBalance")
print("White balance readonly value", property.get_readonly())
print("White balance value currently", property.get_value())
property.set_value("Daylight")
camera.set_config(config)
print("White balance value after setting", property.get_value())
del config
config = camera.get_config()
property = config.get_child_by_id(20)
print("White balance value after reinit", property.get_value())
White balance readonly value 0
White balance value currently Automatic
White balance value after setting Daylight
Traceback (most recent call last):
File "error_test.py", line 18, in <module>
property = config.get_child_by_id(20)
gphoto2.GPhoto2Error: [-2] Bad parameters
Calling get_child_by_id()
and then get_child_by_id()
# Camera initialization not shown
property = config.get_child_by_id(20)
print("White balance readonly value", property.get_readonly())
print("White balance value currently", property.get_value())
property.set_value("Daylight")
camera.set_config(config)
print("White balance value after setting", property.get_value())
del config
config = camera.get_config()
property = config.get_child_by_id(20)
print("White balance value after reinit", property.get_value())
White balance readonly value 0
White balance value currently Automatic
White balance value after setting Daylight
Traceback (most recent call last):
File "error_test.py", line 18, in <module>
property = config.get_child_by_id(20)
gphoto2.GPhoto2Error: [-2] Bad parameters
Note that the del config
is not necessary for the test cases which pass. Something's off about calling get_child_by_id()
a second time without reinitializing camera. Perhaps this is more of a libgphoto2
discussion, but I haven't had the time to take a look at the C source. Feel free to close if you feel this is not relevant to python-gphoto2
!
You need to delete config
and property
(and any other widgets). Every widget keeps a reference to the root of its tree, so the tree is only deleted when all its widgets have been deleted. (This avoids segmentation faults if you carry on using a widget after the root widget has been deleted.)
Your initial examples didn't include set_config
so I misunderstood what you are doing. Getting confirmation is an entirely reasonable thing to try.
You need to delete
config
andproperty
(and any other widgets).
import gphoto2 as gp
import time
camera = gp.Camera()
camera.init()
config = camera.get_config()
print(config)
property = config.get_child_by_id(20)
print("White balance readonly value", property.get_readonly())
print("White balance value currently", property.get_value())
property.set_value("Daylight")
camera.set_config(config)
print("White balance value after setting", property.get_value())
config_two = camera.get_config()
print(config_two)
### Reference Check
print("config is config_two", config is config_two)
property_two = config_two.get_child_by_id(20)
print("White balance value after reinit", property_two.get_value())
<Swig Object of type '_CameraWidget *' at 0x7f60820fc370>
White balance readonly value 0
White balance value currently Automatic
White balance value after setting Daylight
<Swig Object of type '_CameraWidget *' at 0x7f60820fc4f0>
config is config_two False
Traceback (most recent call last):
File "error_test.py", line 21, in <module>
property_two = config_two.get_child_by_id(20)
gphoto2.GPhoto2Error: [-2] Bad parameters
Please correct me if I'm wrong, but the only references to widgets are config
and property
? Python has garbage collection handled, so users should not need to touch garbage collection. As far as I know, calling del
is unnecessary.
Your initial examples didn't include
set_config
so I misunderstood what you are doing. Getting confirmation is an entirely reasonable thing to try.
No worries, that's my fault for not being more clear.
My point is that config
and property
are Python objects both pointing to a C structure (the tree of widgets) which will only be deleted when config
and property
are both deleted. I don't know how the internals of libgphoto2 work, but I thought a possible explanation for your problem might be having two config trees active at the same time. The fact that reinitialising the camera helps suggests things are being cached or otherwise held in memory.
Garbage collection is irrelevant here. It's to do with reference cycles (e.g. deleted objects A & B each have a reference to the other).
Yeah it's just interesting that it only happens with a call to get_child_by_id()
a second time, but not with the other functions. Regardless the reinitialization is not a big deal on my part. Feel free to close the issue and thank you for your time once again.
Try getting property_two
by label and then getting its id. The documentation says get_id
"retrieves the unique id of the CameraWidget" - maybe it's truly unique and not repeated in the second config tree.
I've never played with the widget ids so don't know what they're for.
Oops just saw this. Think we posted at the same time.
Try getting
property_two
by label and then getting its id. The documentation saysget_id
"retrieves the unique id of the CameraWidget" - maybe it's truly unique and not repeated in the second config tree.
Great suggestion. So I guess IDs are dynamic and not necessarily consistent after calling get_config()
a second time. But upon reinitialization it gets reset back to its original ID value.
import gphoto2 as gp
import time
camera = gp.Camera()
camera.init()
config = camera.get_config()
property = config.get_child_by_name("whitebalance")
print("Property ID", property.get_id())
print("White balance readonly value", property.get_readonly())
print("White balance value currently", property.get_value())
property.set_value("Daylight")
camera.set_config(config)
print("White balance value after setting", property.get_value())
config_two = camera.get_config()
property_two = config_two.get_child_by_name("whitebalance")
print("Property two ID", property_two.get_id())
print("Property two name", property.get_name())
print("Property two label", property.get_label())
# Property ID went from 20 to 93.
# Error is thrown here
property_two = config_two.get_child_by_id(20)
print("White balance value after reinit", property_two.get_value())
Property ID 20
White balance readonly value 0
White balance value currently Automatic
White balance value after setting Daylight
Property two ID 93
Property two name whitebalance
Property two label WhiteBalance
Traceback (most recent call last):
File "error_test.py", line 24, in <module>
property_two = config_two.get_child_by_id(20)
gphoto2.GPhoto2Error: [-2] Bad parameters
import gphoto2 as gp
import time
camera = gp.Camera()
camera.init()
config = camera.get_config()
property = config.get_child_by_name("whitebalance")
print("Property ID", property.get_id())
print("White balance readonly value", property.get_readonly())
print("White balance value currently", property.get_value())
property.set_value("Daylight")
camera.set_config(config)
print("White balance value after setting", property.get_value())
config_two = camera.get_config()
property_two = config_two.get_child_by_name("whitebalance")
print("Property two ID", property_two.get_id())
print("Property two name", property.get_name())
print("Property two label", property.get_label())
camera = gp.Camera()
camera.init()
config_three = camera.get_config()
property_three = config_three.get_child_by_id(20)
print("Property three ID", property_three.get_id())
print("Property three name", property_three.get_name())
print("Property three label", property_three.get_label())
Property ID 20
White balance readonly value 0
White balance value currently Automatic
White balance value after setting Daylight
Property two ID 93
Property two name whitebalance
Property two label WhiteBalance
Property three ID 20
Property three name whitebalance
Property three label WhiteBalance
That confirms my supposition rather nicely. If the id is 93 then 20 is an invalid parameter for get_child_by_id
. I think get_child_by_id
is of little use in user programs. Getting widgets by name is probably safest - the label may vary with localisation, or even be duplicated in the widget tree.
If you haven't already tried it, the camera-config-gui.py
example can be used to explore the widget tree.
Original implementation utilizesget_child_by_id()
for the sake of being dynamic in case child names vary between camera manufacturers. However, I currently don't have a wide array of cameras to test against to validate this original thought process. Regardless I'll just access widgets by name for now. And yes camera-config-gui.py
is very handy for widget tree exploration - thank you!
I'll be closing the issue now, so thanks for the support once again.
If the names vary the ids will vary even more! Config trees vary hugely, from a flat list of all the widgets to a multi tab tree of groups of related widgets. Writing anything camera independent will be a challenge. (Downloading pictures, which is my main use of libgphoto2, is much more straightforward. I only added the widget stuff to python-gphoto2 for completeness. I've never made much use of it.)
PS I think the names are "invented" by libgphoto2's authors, possibly with reference to camera makers' software. Binary addresses are all that travels over USB. Some of the widgets on my cameras just have hexadecimal number names, probably because their function hasn't yet been identified by reverse engineering.
Your system What version of Python are you using?
What version of libgphoto2 have you installed?
How have you installed (or attempted to install) python-gphoto2?
Your problem Hello Jim, sorry I'm back with another issue so shortly after we just closed my previous one. I get the error
gphoto2.GPhoto2Error: [-2] Bad parameters
when trying to access_CameraWidget *
pointer methods, but only if I call theCamera.get_config()
more than once.Train of Thought If I wanted to modify a camera property's value, I would like to check if it updated successfully. For example, I would first find the property by ID with
_CameraWidget.get_child_by_id()
and then assuming it passes error checks and it's notreadonly
, I would update the value with_CameraWidget.set_value()
. However, sometimes you're able to successfully modify a value (error checking returns0
), but in actuality the camera property doesn't actually change on (i.e. it was physically set to a different mode). Getting the camera summary again shows that it doesn't actually update. I've been passing around my initial config fromCamera.get_config()
so checking that value shows that it supposedly did successfully update - but we know that's not the case.Error Recreation
In the above example, we see it can successfully get the camera property via its name, and running
_CameraWidget.get_name()
method validates this. However the error is thrown when trying to later get the property by ID, with the_CameraWidget.get_child_by_id()
method.However, calling
get_config()
multiple times, and getting the property by the same previous method throws no errors.And when calling
get_config()
just once, things work as expected:And the workaround seems to be just reinitializing the
Camera *
object.Please advise and let me know if my interpretation in the use of methods is invalid, or this is behaving as expected. Thank you for your time once again.