TypeError when trying to get container instance status
When trying to get the status of a container instance running on a remote podman host, I get the following error.
Out[5]: <Container: 859c3172e0>
In [6]: container_inst.id
Out[6]: '859c3172e0de5e27934ba7bcbd190d0949227bfe973ded77658d25f30a1585c2'
In [7]: container_inst.status
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[7], line 1
----> 1 container_inst.status
File ~/Programming/broker/.venv/lib64/python3.12/site-packages/podman/domain/containers.py:54, in Container.status(self)
52 """Literal["running", "stopped", "exited", "unknown"]: Returns status of container."""
53 with suppress(KeyError):
---> 54 return self.attrs["State"]["Status"]
55 return "unknown"
TypeError: string indices must be integers, not 'str'
When checking the value of attrs for the instance, I see that status isn't nested under state.
In [1]: self.attrs
Out[1]:
{'AutoRemove': False,
'Command': ['/bin/sh', '-c', '/tmp/startup.sh'],
...
'StartedAt': 1728929152,
'State': 'running',
'Status': ''}
There is also a possibility that this is due to a difference in major podman versions.
Local Podman: podman-5.2.3-1.fc40.x86_64 Local podman-py: 5.0.0 Remote Podman: podman-4.9.4-4
@JacobCallahan thanks for the report, I think it could be due to Podman 4 on the host and Podman 5 on the client. Do you have the chance to try with the same major versions?
@inknos unfortunately, I don't have a remote podman host now, but could potentially set one up on Friday or next week.
@JacobCallahan , I tried to reproduce it and it works on my system with podman 5 in the host and podman 4 in the server. I think trying with podman 5 in both is not necessary.
>>> url = "ssh://[email protected]/run/user/1000/podman/podman.sock"
>>> from podman import PodmanClient
>>> client = PodmanClient(base_url=url, identity="/home/nsella/.ssh/id_rsa")
>>> client.containers.list()
[<Container: fd7dec82e8>, ... ]
>>> c = client.containers.get("fd7dec82e8")
>>> c.id
'fd7dec82e85daac28395403fc130411c6ee72e4b4d73e4a9ecf56dceeed42390'
>>> c.status
'running'
Host: podman version 5.3.0-dev-27d73b0cd
Server: podman version 4.9.4-rhel
PodmanPy: upstream and 5.0.0
Please provide more information on your issue. do my steps reproduce the issue for you? if not, could you provide reproducing steps?
@inknos so i found something interesting while testing your steps. Your steps worked fine, when acting on a container object from get, but not on the container objects returned from list.
In [6]: url = "tcp://infra-podman-ipv4.our.lab.com:2375"
In [7]: client = PodmanClient(base_url=url)
In [8]: client.containers.list()
Out[8]:
[<Container: abb2858b55>,
<Container: f4539e8307>,
<Container: 8c106a4a5a>,
<Container: 6b9a4e97a2>,
<Container: 43850b849c>,
<Container: 7f5afe54bf>,
<Container: e27ea6295c>,
<Container: c13ed5f868>,
<Container: 859c3172e0>,
<Container: acefe65b89>]
In [9]: c = client.containers.get("abb2858b55")
In [10]: c.id
Out[10]: 'abb2858b558831055a74c9b79f4db1bf0e60b7c3f47a144ee05fe9c59edebeae'
In [11]: c.status
Out[11]: 'running'
In [12]: for c in client.containers.list():
...: print(c.id)
...: print(c.status)
...:
abb2858b558831055a74c9b79f4db1bf0e60b7c3f47a144ee05fe9c59edebeae
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[12], line 3
1 for c in client.containers.list():
2 print(c.id)
----> 3 print(c.status)
File ~/Programming/broker/.venv/lib64/python3.12/site-packages/podman/domain/containers.py:54, in Container.status(self)
52 """Literal["running", "stopped", "exited", "unknown"]: Returns status of container."""
53 with suppress(KeyError):
---> 54 return self.attrs["State"]["Status"]
55 return "unknown"
TypeError: string indices must be integers, not 'str'
In [13]: containers = client.containers.list()
In [14]: containers[0].id
Out[14]: 'abb2858b558831055a74c9b79f4db1bf0e60b7c3f47a144ee05fe9c59edebeae'
In [15]: containers[0].status
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[15], line 1
----> 1 containers[0].status
File ~/Programming/broker/.venv/lib64/python3.12/site-packages/podman/domain/containers.py:54, in Container.status(self)
52 """Literal["running", "stopped", "exited", "unknown"]: Returns status of container."""
53 with suppress(KeyError):
---> 54 return self.attrs["State"]["Status"]
55 return "unknown"
TypeError: string indices must be integers, not 'str'
right, so the issue is that the container status need to be reloaded in order to access it from the list. note that the inspect call is expensive, that's why you need to run reload explicitly.
clist = client.containers.list()
for c in clist:
c.reload()
print(clist[0].status)
with this you should get the status.
I would not touch too much the reload function but something I would consider is handling such exceptions with a try like
@property
def status(self):
"""Literal["running", "stopped", "exited", "unknown"]: Returns status of container."""
with suppress(KeyError):
try:
return self.attrs["State"]["Status"]
except TypeError as e:
# stderr or log something useful here
# probably even raise e again since I am not sure TypeError would isolate this issue
return "unknown"
cc: @jwhonce TL;DR: we are once again discussing status property exceptions when it's invoked after a container.list call
I would propose two approaches
-
containers.listcallsc.reload()beforereturn- https://github.com/containers/podman-py/commit/2c6806ba808d7f4dfb71080c67606a275c26cecc -
c.statusreturn "unknown" ifTypeError- https://github.com/containers/podman-py/commit/fa92dd71d9a42f0e2801607fb895a52b3b17a58f
The expense has to be paid by someone, to be fair.
As a user, I would expect the Container objects from list to be the same as those from get. Having to get the initial list of container objects, then iterating over those objects just to pull the full information again doesn't seem ideal.
I've worked around this issue for my team's use with a try/except in the meantime.
try:
info["status"] = container_inst.status
except TypeError:
info["status"] = container_inst.attrs["State"]
edit: If the intention isn't to have the container object be complete when returning from list, then you could just return a list of ids and make sure users call get manually. This would certainly speed things up from that perspective..
@inknos I would rather see us implement the sparse keyword for list(). It is currently ignored.