Skip to content

Commit 446b604

Browse files
[docs] Update documentation
1 parent ebc4764 commit 446b604

File tree

2 files changed

+121
-5
lines changed

2 files changed

+121
-5
lines changed

docs/changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## v0.4.0
22

3+
* Add events support in Python scripts
4+
* Improve Python scripts run
5+
* Add common libraries for a Python
6+
* Fix memory leaks in core
37
* Improve test logging
48
* Improve work with memory buffers
59
* Cleanup API

docs/python/python.md

Lines changed: 117 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,123 @@
11
# Python
22

3-
You can implement agents using python. All python modules should be implemented with specified rules.
3+
You can implement agents using **Python 3**. All python modules should be implemented with specified rules.
44

5-
1. Each module, that implement agent should be names by this rule: `a_<agentName>.py`. That allows system to
6-
know which modules could be used to run. Util modules and others should be named NOT using this rule.
5+
1. You can specify search paths of a python modules by `python.modules_path` value in a [configuration file](../other/config.md).
76

8-
2. You can specify search paths of a python modules by `python.modules_path` value in a [configuration file](../other/config.md).
7+
8+
# Usage example
9+
There are two ways to run python script:
10+
11+
- when you need run script and wait it finished, then just use this code:
12+
```cpp
13+
#include <sc-memory/cpp/python/sc_python_interp.hpp>
14+
...
15+
void doSomething()
16+
{
17+
...
18+
py::ScPythonInterpreter::RunScript("lg/tv_service.py", m_bridge);
19+
...
20+
}
21+
```
22+
Then in python you can write any code you want:
23+
```python
24+
import any_module
25+
26+
# create context (with minimal access)
27+
ctx = createScMemoryContext('context name')
28+
29+
# create node
30+
nodeAddr = ctx.CreateNode(ScType.NodeConst)
31+
...
32+
33+
# you can use any installed python libraries
34+
any_module.doSomething()
35+
```
36+
37+
- if you want to run script as a service and communicate with it, then use code:
38+
```cpp
39+
class Service
40+
{
41+
public:
42+
void Run()
43+
{
44+
// Run script in a separate thread
45+
m_workThread.reset(new std::thread([&]
46+
{
47+
// should exist my/my_script.py in python modules path
48+
py::ScPythonInterpreter::RunScript("my/my_script.py", m_bridge);
49+
}));
50+
m_workThread->detach();
51+
52+
// wait until bridge starts
53+
m_bridge->WaitInitialize();
54+
55+
// now you can use bridge
56+
ScPythonBridge::ResponsePtr res = m_bridge->DoRequest("eventName", "eventData");
57+
}
58+
59+
void Stop()
60+
{
61+
m_bridge->Close(); // close bridge
62+
m_workThread->join(); // wait until thread finished
63+
}
64+
65+
private:
66+
py::ScPythonBridgePtr m_bridge; // special bridge to communicate with python script
67+
std::unique_ptr<std::thread> m_workThread; // thread where script runs
68+
};
69+
```
70+
71+
Then in python code use common module:
72+
```python
73+
from common import ScModule
74+
75+
class MyModule(ScModule):
76+
77+
kNrelMainIdtf = 'nrel_main_idtf'
78+
kDevice = 'device'
79+
80+
def __init__(self):
81+
ScModule.__init__(self,
82+
createScMemoryContext('MyModule'), keynodes=[
83+
# there we can initialize keynodes that we need
84+
MyModule.kNrelMainIdtf,
85+
MyModule.kDevice,
86+
], cpp_bridge=cpp_bridge)
87+
# cpp_bridge - is a global variable that store CPP-Python bridge object
88+
89+
90+
def OnCppUpdate(self):
91+
super.OnCppUpdate(self)
92+
# you can overload more functions for work
93+
# see more details in sc-kpm/python/common/sc_module.py
94+
95+
def printMainIdtf(self):
96+
# template to update current volume value
97+
templ = ScTemplate()
98+
templ.TripleWithRelation(
99+
self.keynodes[self.kDevice], # get ScAddr of keynode
100+
ScType.EdgeDCommonVar,
101+
ScType.Link >> '_link',
102+
ScType.EdgeAccessVarPosPerm,
103+
self.keynodes[self.kNrelMainIdtf])
104+
105+
# self.sc_context - is a context to work with sc-memory (use just this one)
106+
searchResult = self.sc_context.HelperSearchTemplate(templ)
107+
108+
linkAddr = None
109+
if searchResult.Size() > 0:
110+
# we found old value change it
111+
linkAddr = searchResult[0]['_link']
112+
else:
113+
genResult = self.sc_context.HelperGenTemplate(templ, ScTemplateGenParams())
114+
if genResult:
115+
linkAddr = genResult['_link']
116+
117+
if linkAddr:
118+
print(self.sc_context.GetLinkContent(linkAddr))
119+
120+
```
9121

10122
# Classes
11123

@@ -306,7 +418,7 @@ for i in range(resultNum):
306418
## ScMemoryContext
307419

308420
This class implements context, that allows you to work with memory.
309-
<div class="note"><b>You shouldn't share one context between two or more threads</b></div>
421+
<div class="note"><b>DO NOT use one context in different threads</b></div>
310422
There are methods of this class:
311423

312424
- `CreateNode(type)` - create node with specified type. Where `type` is an instance of `ScType` (just **edge** types could be used). Returns `ScAddr` of created node. If returned `ScAddr` is not valid (`IsValid()`), then node wasn't created.

0 commit comments

Comments
 (0)